Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Craig Cronin 304 posts 503 karma points
    Aug 11, 2015 @ 10:17
    Craig Cronin
    0

    MVC partial view filter problems???

    I'm still trying to get my head around mvc implementation in Umbraco but currently stuck on a problem.

    I have a template with two Html.Action partial views.

    1. The first will shows the results from a filter http://www.merthyr.gov.uk/council/data-protection-and-freedom-of-information/disclosure-log

    2. The second is a side filter.

    If i select a filter value from years ago which generates enough results for the pagination to kick it all works.

    Once I select to move to the next page, it doesn't work.

    [ChildActionOnly]
        public ActionResult DisplayGet()
        {            
            return PartialView("~/Views/Partials/Foi/DisplayFoi.cshtml", new List<DisplayViewModel>());
        }
    
    [HttpPost]
        public ActionResult DisplayPost(DisplayFilterViewModel filter)
        {
            var from = new DateTime(1753, 1, 1);
            var to = DateTime.MaxValue;
    
            if (filter.FromDate.HasValue)
                from = (DateTime)filter.FromDate;
    
            if (filter.ToDate.HasValue)
                from = (DateTime)filter.ToDate;
    
            var model = _foiQuestionService.GetFoiQuestions(filter.Category, filter.Keyword, from, to)
                .Select(s => new DisplayViewModel()
                {
                    Id = s.Id,
                    FileRef = s.Foi.FileRef,
                    Question = s.Question,
                    DateRequestReceived = s.Foi.DateRequestReceived
                }).ToList();
    
            TempData.Add("DisplayViewModel", model);
    
            return CurrentUmbracoPage();
        }
    
    [ChildActionOnly]
        public ActionResult DisplayItem(int id)
        {
            var foi = _foiQuestionService.GetFoiQuestion(id);
    
            var model = new DisplayItemViewModel()
            {
                Id = foi.Id,
                FileRef = foi.Foi.FileRef,
                DateRequestReceived = foi.Foi.DateRequestReceived,
                DateRequestCompleted = foi.Foi.DateRequestCompleted,
                ApplicationType = foi.Foi.ApplicationType.ApplicationType,
                Category = foi.QuestionCategory.QuestionCategory,
                Question = foi.Question,
                Organisation = foi.Foi.Organisation == null ? "" : foi.Foi.Organisation.Organisation,
                Answer = foi.Answer,
                Documents = _foiQuestionDocumentService.GetFoiQuestionDocuments(id)
                    .Select(s => new QuestionDocumentViewModel()
                    {
                        Id = s.Id,
                        DocumentName = s.DocumentName,
                        Document = s.Document
                    }).ToList()
            };
    
            TempData.Add("DisplayItemViewModel", model);
    
            return PartialView("~/Views/Partials/Foi/DisplayFoiItem.cshtml", model);
        }
    
  • Shannon Deminick 1524 posts 5270 karma points MVP 2x
    Aug 17, 2015 @ 14:22
    Shannon Deminick
    0

    That's because you are mixing Http POSTs and GETs.

    • You are POSTing data to a form, creating a model from it, chucking it into TempData and returning the view.
    • Then, you have links (GET) to go to a page with a query string for your page number.... at no point in time does your DisplayPost(DisplayFilterViewModel filter) execute again

    Normally this sort of thing is all done with GETs especially because your form data is just filters and it can easily be put into a query string. The other problem with this implementation is that you are putting everything into TempData and then using that in your child action to render data. This is not a very good way to work with MVC. It's also worth nothing that TempData should only ever be used when you are redirecting ... this is the sole reason it exists. Since you are not redirecting, if you want to continue down this path, you should use ViewData.

    Here's what you should do:

    • Your form should be a GET not a POST
    • You should have a single ChildAction to display your paged data, it could accept a DisplayFilterViewModel as a parameter if your query string parameters can bind to that model, or you can bind each query string valu as individual parameters (this is standard ASP.Net MVC)
    • You'd then have your normal filtering logic and return a partial view with your model
    • You should not need any HttpPost method
    • You should not need or use any TempData
  • Craig Cronin 304 posts 503 karma points
    Aug 17, 2015 @ 14:28
    Craig Cronin
    0

    Hi Shannon,

    Thanks for getting back to me on this. I don't think my example shows but I use the same page for showing the item detail e.g

    1. User goes to the page which is empty.
    2. They select from filter widget on the side
    3. This displays the results in a table.
    4. The user then selects the desired row and the details is shown

    Based on this, will your solution still work?

  • Shannon Deminick 1524 posts 5270 karma points MVP 2x
    Aug 17, 2015 @ 14:51
    Shannon Deminick
    0

    That would work fine, all you are doing is out-putting a different partial view/model based on what is in your query strings.

  • Craig Cronin 304 posts 503 karma points
    Aug 17, 2015 @ 15:23
    Craig Cronin
    0

    Thanks Shannon,

    Will give this a try in the morning.

  • Craig Cronin 304 posts 503 karma points
    Aug 18, 2015 @ 13:32
    Craig Cronin
    0

    Hi Shannon,

    When I do this

    public ActionResult DisplayGet(DisplayFilterViewModel filter)
        {
            var category = filter.Category + "";
            var keyword = filter.Keyword + "";
            var from = new DateTime(1753, 1, 1);
            var to = DateTime.MaxValue;
    
            if (filter.FromDate.HasValue)
                from = (DateTime)filter.FromDate;
    
            if (filter.ToDate.HasValue)
                from = (DateTime)filter.ToDate;
    
            var model = _foiQuestionService.GetFoiQuestions(category, keyword, from, to)
                .Select(s => new DisplayViewModel()
                {
                    Id = s.Id,
                    FileRef = s.Foi.FileRef,
                    Question = s.Question,
                    DateRequestReceived = s.Foi.DateRequestReceived
                }).ToList();
    
            return PartialView("~/Views/Partials/Foi/DisplayFoi.cshtml", model);
        }
    

    It returns the partialview back to a blank page. This is where I stumbled when I first looked at this, and is why I ended up coming across the tempdata, solution?

  • Craig Cronin 304 posts 503 karma points
    Aug 18, 2015 @ 13:40
    Craig Cronin
    0
    @if (Request.QueryString["id"] == null || Request.QueryString["id"] == "")
    {
          @Html.Action("DisplayGet", "FoiSurface")
    }
    else
    {
    @Html.Action("DisplayItem", "FoiSurface", new { id = Request.QueryString["id"] })
    }
    
    @section widgets {
            @if (Request.QueryString["id"] == null || Request.QueryString["id"] == "") {
    @Html.Action("DisplayFilter", "FoiSurface")
    }
    }
    

    My current view that displays, the filter, summary and detail

  • Shannon Deminick 1524 posts 5270 karma points MVP 2x
    Aug 18, 2015 @ 14:07
    Shannon Deminick
    0

    I'm assuming you are sending your form to the DisplayGet action?

    Let me try to explain what is happening as there's clearly a bit of confusion as to what is happening.

    • Umbraco renders your page
    • Inside of this page you have a form which gets sent to a SurfaceController action (either by a GET or a POST)
    • This MVC Action is executed, just like any normal ASP.Net MVC action
    • In this action you are currently returning return PartialView("~/Views/Partials/Foi/DisplayFoi.cshtml", model). ... which is doing exactly what it says: it's returning a partial view ... and this is outside of the Umbraco pipeline, this is the exact same thing that would happen if you created a normal ASP.Net MVC app, sent your data to an Action and just returned a partial view

    When you return anything from a SurfaceController action that you are sending form data to, you need to either return CurrentUmbracoPage() or RedirectToCurrentUmbracoPage().

    TempData is used only for redirecting.

    Have you read this? It explains in detail the routing process: https://our.umbraco.org/documentation/reference/Templating/Mvc/forms

  • Craig Cronin 304 posts 503 karma points
    Aug 18, 2015 @ 15:10
    Craig Cronin
    0

    yes, I'm sending the form to DisplayGet.

    It feels like I should be looking for return CurrentUmbracoPage(model)

    I need to return the view but with the current page.

    Just looking at the link you sent :)

  • Shannon Deminick 1524 posts 5270 karma points MVP 2x
    Aug 18, 2015 @ 15:18
    Shannon Deminick
    100

    The link and examples should help you understand the process a little more.

    In the meantime, here's where your implementation is incorrect:

    You don't need to send data anywhere, your html form doesn't even need to be an Umbraco form. It could literally just be:

    <form action="@Request.Url.AbsolutePath" method="GET">

    This is simply going to reload your page with the form values as query strings.

    Then all you need to do is have the logic in your ChildAction that looks up your content and displays it. For what you are doing, there's not need for a Controller Action to handle your form request, all you want is for the form to populate the query strings.

  • Craig Cronin 304 posts 503 karma points
    Aug 18, 2015 @ 15:25
    Craig Cronin
    0

    Thanks Shannon,

    This seems to be the solution. I'm going to read over the links you've sent so that I completely understand the process tomorrow.

    Really appreciate the help.

  • Shannon Deminick 1524 posts 5270 karma points MVP 2x
    Aug 18, 2015 @ 15:48
    Shannon Deminick
    0

    Cool, just keep in mind that the links sent are about POSTing data to forms whereas your implementation doesn't require that since it's just a filter based on query strings

Please Sign in or register to post replies

Write your reply to:

Draft