Copied to clipboard

Flag this post as spam?

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


  • jho 3 posts 35 karma points
    Jan 10, 2015 @ 23:20
    jho
    2

    Calling controller action from partial view

    First time poster, long time reader :)

    I am trying to learn Umbraco MVC and I am stuck with a problem I cannot seem to work out. I want to create a page containing a table, with clickable table-headers. When clicking on a table-header, the table is sorted according to the header.

    My idea is to render the table in a partialview. The table header-links should be generated using Html.RenderActionLink, which reference an action in a SurfaceController (or RenderMvcController), that returns a sorted list of content.

    This is my setup:

    View

    @inherits UmbracoTemplatePage<DocumentType>
    
    ...code...
    
    @{ Html.RenderPartial("ListAllAssignments", TempData["viewModel"] ?? new AssignmentViewModel(Model)); }
    

    PartialView - ListAllAssignments.cshtml:

    @inherits UmbracoViewPage<AssignmentViewModel>
    
    <div>
       <table>
            <tr>
                <td>
                    @Html.ActionLink("[ID]", "SortBy", "AssignmentSurface", new { nodeId = Model.CurrentPage.Id, sortCategory = SortCategory.ID }, null)
                </td>
        </tr>
           table data here
        </table>
    </div>
    

    Controller:

    public class AssignmentSurfaceController : SurfaceController
    {
            [AcceptVerbs(HttpVerbs.Get)]
            public ActionResult SortBy(int nodeId, SortCategory sortCategory)
            {
                var overviewPage = DocumentTypeHelper.GetDocument<AssignmentOverviewPage>(nodeId);
                var assignmentViewModel = new AssignmentViewModel(overviewPage);
                var assignments = new AssignmentManager().GetAll();
    
                switch (sortCategory)
                {
                    case SortCategory.ID:
                        assignments = assignments.OrderBy(x => x.ID);
                        break;
                    default:
                        return null;
                }
    
                assignmentViewModel.AllAssignments = assignments.ToList();
                TempData["viewModel"] = assignmentViewModel;
    
                return RedirectToCurrentUmbracoPage();
            }
    }
    

    However, clicking the header in the table results in an error:

    Cannot find the Umbraco route definition in the route values, the request must be made in the context of an Umbraco request

    What am I doing wrong?

    Best regards

  • Alex Skrypnyk 6182 posts 24284 karma points MVP 8x admin c-trib
    Jan 11, 2015 @ 01:12
    Alex Skrypnyk
    0

    Hi jho ,

    You have to try define exactly url of request. Did you change something in routing ?

    Thanks

  • Cimplex 113 posts 576 karma points
    Jan 11, 2015 @ 01:33
    Cimplex
    101

    Hi jho, Whats happening here is that the surface controller dosent know what page you coming from and cant return "CurrentUmbracoPage" with the Html.ActionLink.

    I would solve this using a RenderMvcController and pass in the sorting category to it and from the controller return a custom RenderModel to get rid of your TempData fields.

    Create a RenderMvcController naming it: Document Type name = controller name Template name = action name and create a view model

    public class HomeController : Umbraco.Web.Mvc.RenderMvcController
    {
        public ActionResult HomePage(RenderModel model, int sort)
        {
            var viewModel = new HomePageViewModel(model.Content)
                                {
                                    Sort = sort
                                };
    
            return base.Index(viewModel);
        }
    }
    
    
    public class HomePageViewModel : RenderModel
    {
        public HomePageViewModel(IPublishedContent content)
            : base(content)
        {
        }
    
        public int Sort { get; set; }
    }
    

    Then you can use a Html.Action to render your partial. Like this:

    @Html.Action("SortBy","AssignmentSurface", new { nodeId = Model.Content.Id, sortCategory = Model.Sort })
    

    And finally in your Surface controller return the partialview:

    public class AssignmentSurfaceController : SurfaceController
    {
            [AcceptVerbs(HttpVerbs.Get)]
            public ActionResult SortBy(int nodeId, SortCategory sortCategory)
            {
                var overviewPage = DocumentTypeHelper.GetDocument<AssignmentOverviewPage>(nodeId);
                var assignmentViewModel = new AssignmentViewModel(overviewPage);
                var assignments = new AssignmentManager().GetAll();
    
                switch (sortCategory)
                {
                    case SortCategory.ID:
                        assignments = assignments.OrderBy(x => x.ID);
                        break;
                    default:
                        return null;
                }
    
                assignmentViewModel.AllAssignments = assignments.ToList();
                TempData["viewModel"] = assignmentViewModel;
    
                return PartialView("ListAllAssignments", assignmentViewModel);
            }
    }
    

    Your sorting urls would now look like this:

    <a href="@(Model.Content.Url + "?sort=" + 123)">Sort</a>
    

    Good luck!

  • jho 3 posts 35 karma points
    Jan 11, 2015 @ 13:26
    jho
    0

    Hi Cimplex

    Thank you for your suggestion! It almost works :)

    However, now I am recieving this exception:

    The parameters dictionary contains a null entry for parameter 'sort' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult AssignmentOverviewPage(Umbraco.Web.Models.RenderModel, Int32)' in 'AssignmentOverviewPageController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
    

    I did not change anything in the routing-table so far - but maybe I have to?

    This is my RenderMvcController:

    public class AssignmentOverviewPageController : RenderMvcController
    {
        public ActionResult AssignmentOverviewPage(RenderModel model, int sort)
        {
            var viewModel = new AssignmentViewModel(model.Content)
            {
                Sorting = sort
            };
            return base.Index(viewModel);
        }
    }
    

    This is the view of my RenderMvcController:

    @inherits UmbracoViewPage<AssignmentViewModel>
    <h2>AssignmentOverviewPage</h2>
    <div>    
        @Html.Action("SortBy", "AssignmentSurface", new { nodeId = Model.Content.Id, sortCategory = Model.Sorting });
    </div>
    
  • Cimplex 113 posts 576 karma points
    Jan 11, 2015 @ 13:33
    Cimplex
    0

    Hi jho,

    Try this:

    public ActionResult HomePage(RenderModel model, int? sort) {
    
    if(sort != null)
    // add value to your model like this (int)sort
    }
    else {
    // set the default sort value to the model
    }
    
    }
    

    The questionmark after the int will allow sort to be null.

  • jho 3 posts 35 karma points
    Jan 11, 2015 @ 13:47
    jho
    0

    Making sort nullable solved it.

    Thank you very much for the help - appreciated :)

    I'll mark your first post as the answer since that contains the majority of the changes I had to perform.

  • Willem Luijk 24 posts 95 karma points
    Sep 12, 2015 @ 00:30
    Willem Luijk
    0

    Dow anybody knows where i can find the DocumentTypeHelper from this example?

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies