سؤال

I have a MVC project using EF which contains many projects (name, description, deadline, etc). They also have certain things such as a region associated with them and their active state (in process, inactive, etc...). What I am trying to do is filter from these using a telerik dropdown list via a partial view. I am also attempting to save the filters last state in a cookie on change.

The problem I am having is that when I do change the filters the on-change event does not always get called.

The index is used to load the outer shell of the application this includes.

  1. The telerik dropdowns are created using the Viewbag with on-change events
  2. Load projects for the partial view
  3. Generates a navigation menu at the top for other webpages regarding projects

The cookies state is read here for the first instance on the page loading.

        [HttpGet]
        public ActionResult Index()
        {

            int Region_ID = -1;
            int State_ID = -1;

            if (this.ControllerContext.HttpContext.Request.Cookies.AllKeys.Contains("Cookie"))
            {
                List<string> str = this.ControllerContext.HttpContext.Request.Cookies["Cookie"].Value.Split(',').ToList<string>();
                Region_ID = Convert.ToInt32(str[0]);
                State_ID  = Convert.ToInt32(str[1]);

            }

            db = new DashboardEntities();
            var filterRegion = new SelectList(db.Region.Where(m => m.Active).OrderBy(n => n.Name), "ID", "Name",Region_ID).ToList();
            var filterState = new SelectList(db.State.Where(m => m.Active).OrderBy(n => n.Name), "ID", "Name",State_ID).ToList();


            filterRegion.Insert(0, new SelectListItem { Text = "All", Value = "-1" });
            filterState.Insert(0, new SelectListItem { Text = "All", Value = "-1" });

            ViewBag.FilterRegionSelectList = filterRegion;
            ViewBag.FilterStateSelectList = filterState;

            var prj = (db.Project.Include("Builder").Include("ProjectNotes").Where(m => m.Builder.Region_ID == Region_ID || Region_ID == -1)
                      .Where(m => m.State_ID == State_ID || State_ID == -1)

            return View(prj);
        }

The partial is used to display filter changes after first loading the page. Also when the filter changes the cookie is updated here when reloading the correct collection of projects.

    public PartialViewResult DashboardPartial(int id, int state )
    {
        db = new DashboardEntities();

        var filterRegion = new SelectList(db.Region.Where(m => m.Active).OrderBy(n => n.Name), "ID", "Name", id).ToList();
        var filterState = new SelectList(db.State.Where(m => m.Active).OrderBy(n => n.Name), "ID", "Name", state).ToList();


        filterRegion.Insert(0, new SelectListItem { Text = "All", Value = "-1" });
        filterState.Insert(0, new SelectListItem { Text = "All", Value = "-1" });


        ViewBag.FilterRegionSelectList = filterRegion;
        ViewBag.FilterStateSelectList = filterState;


        HttpCookie cookie = new HttpCookie("Cookie");
        cookie.Value = id.ToString() + "," + state.ToString() ;
        this.ControllerContext.HttpContext.Response.Cookies.Add(cookie);

        var prj = db.Project.Include("Builder").Include("ProjectNotes").Where(m => m.Builder.Region_ID == id || id == -1)
                  .Where(m => m.State_ID == state || state == -1);

        ViewBag.Model = prj;

        return PartialView(prj);
    }

The view contains some javascript to handle the on-change events. I do this by making the telerik dropdown list's on-change event the filterChange() function.

@using Dashboard.Helpers

@{
    ViewBag.Title = "Dashboard";
}


<script type="text/javascript">

    function filterChange() {
        $("#log").ajaxError(function (event, jqxhr, settings, exception) {
            alert(exception);
        });

        var regionValue = $('#filterRegion').data('tDropDownList').value();
        var stateValue = $('#filterState').data('tDropDownList').value();


        //alert('Index: ' + regionValue.toString() + ',' + stateValue.toString());


        $.get('@Url.Action("DashboardPartial")',
        { id: regionValue.toString(), state: stateValue.toString() }, function (data) {
            $("#target").html(data);
        });

    }
</script>

<div style="width: 100%; height: 100%">
    <fieldset>     
        <legend>Filters</legend>
        <div>
            @using (Html.BeginForm())
            {
            <div class="Filter-Div">
                <div style="float: left;">
                    @Html.Label("Region:")
                </div>
                <div style="float: left;">
                    @Html.Telerik().DropDownList().Name("filterRegion").BindTo((List<SelectListItem>)@ViewBag.FilterRegionSelectList).ClientEvents(events => events.OnChange("filterChange"))
                </div>
            </div>
            <div class="Filter-Div">
                <div style="float: left;">
                    @Html.Label("Project State:")
                </div>
                <div style="float: left;">
                    @Html.Telerik().DropDownList().Name("filterState").BindTo((List<SelectListItem>)@ViewBag.FilterStateSelectList).ClientEvents(events => events.OnChange("filterChange"))
                </div>
            </div>

            <div class="Filter-Div">
                <table class="noborder">
                    <tr class="noborder"> <input type="submit" value="Export" name="btnName" /> </tr>   
                </table>
            </div>
            }

        </div>
    </fieldset>  
    @(Html.Telerik().ScriptRegistrar()
    .DefaultGroup(group => group
                .Add("telerik.common.js")
                .Add("telerik.tabstrip.min.js")
                .Add("telerik.calendar.min.js"))
    .jQuery(false))  
    <div>
     @if (User.IsInRole("SuperUser") || User.IsInRole("Admin"))
     {   
        @Html.ActionLink("Create New", "Create", new { controller = "Dashboard", page = "Index" }, new { @class = "t-button" })
     }
    </div>
</div>

<div id="target">
   @{ Html.RenderPartial("DashboardPartial"); 

   }
</div>

Please be aware that I am new to MVC and the entity framework therefore if you see a way to improve the code in anyways. Thank you for any assistance.

Side note - I am currently working on implementing a Viewmodel representation of projects instead of passing the EF directly to the View.

هل كانت مفيدة؟

المحلول

I fixed the problem.

The problem was that by default the partial view was being cached for all of the partial view results generated in that session. As such the partial action was not posted back every time the filters were changed. I was able to limit the caching to a more appropriate length of time using the OutputCache HTML attribute on my partial action.

[OutputCache(Duration=(number of seconds))] 
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top