Copied to clipboard

Flag this post as spam?

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


  • Nancy A. 44 posts 175 karma points
    May 29, 2019 @ 14:31
    Nancy A.
    0

    Getting a HTML.ActionLink to work for a partial view

    In my view, I have a partial view that pulls in a list of posts. On the sidebar, there is a list of categories that, when a user clicks on, re-generates the partial view but filtered by category type (pass via query string in the HTML.ActionLink). The category type, in Umbraco, is a custom drop-down list that the editor is to select from for each post (limited to one category). The problem is that the test link generates the following error: "There is no current PublishedContentRequest, it must be initialized before the RenderRouteHandler executes".

    What is the best way to go about this, to get this id back to the controller for the query within the partial view?

    In the view, I have this:

    @inherits Umbraco.Web.Mvc.UmbracoViewPage
    
    @{
        Layout = "webBase.cshtml";
    }
    
    @* the fun starts here *@
    
    <section class="section--spacing">
        <div class="container">
            <div class="row">
                <!-- Posting Section
                ================================================== -->
                <div class="col-md-8">
                    <div class="post">
                        <h2 class="section__header">News</h2>
                        @{ Html.RenderAction("RenderListOfArticles", "News");}
                    </div>
                </div> <!--col-md-9-->
    
                <div class="col-md-4">
    
                                <h3>Categories</h3>
                                <ul>
    
                                    @Html.ActionLink("Testing", "RenderListOfArticles", "News", new { category = "currentevents"} )
    </div>
                    </div>
    
                </div>
            </div>
        </div>
    </section>
    

    The partial view code is as follows:

    @model IEnumerable<cms.ViewModels.ArticleVM>
    
    
      @foreach (var article in Model)
        {
            <div class="row row--padding row--padding--top post-font">
                <div class="col-md-2">
                    <h4 class="date--color">@article.ArticlePublishDate.ToString("MMM dd")</h4>
                </div>
                <div class="col-md-10">
                    <a href=""><h4 class="post__title--size">@article.ArticleTitle</h4></a>
                    <p class="post__author">@article.ArticleAuthor</p>
                    <p>@article.ArticleExcerpt <a href="@article.ArticleUrl">... Read more</a></p>      
                </div>
            </div>
        } 
    

    and then in the News controller, I have

    namespace cms.Controllers
    {
        public class NewsController : SurfaceController { 
            private string PartialViewPath(string name)
            {
                return $"~/Views/Partials/News/{name}.cshtml";
            }
    
            public ActionResult RenderListOfArticles(string category)
            {
    
                List<ArticleVM> model = new List<ArticleVM>();
                IPublishedContent news = CurrentPage.DescendantOrSelf("news");
    
                foreach (IPublishedContent post in news.Children.Where(x => x.IsVisible()) )
                {
    
                    var getImage = post.Value<IPublishedContent>("articleLeadPicture");
                    var getImageUrl = getImage.Url;
                    model.Add(new ArticleVM(post.Value<DateTime>("articlePublishDate"), post.Value<string>("articleTitle"), post.Value<string>("articleAuthor"),post.Value<string>("articleExcerpt"), post.Value<string>("articleBody") , post.Value<string>("articleTitle"), getImage.Url, post.Url));
                }
    
                IEnumerable<ArticleVM> final;
    
                if (category == " " || category == null)
                {
                    final = model.OrderByDescending(x => x.ArticlePublishDate);
                }
                else
                {
                    final = model.OrderByDescending(x => x.ArticlePublishDate)
                            .Where(x => x.ArticleCategory == category);                   
                }
    
                return PartialView(PartialViewPath("_ListOfArticles"), final);
            }
        }
    }
    
  • Mario Lopez 168 posts 952 karma points MVP 4x c-trib
    May 30, 2019 @ 02:35
    Mario Lopez
    100

    You can't use a Surface Controller in the ActionLink because the controller needs that Context it's complaining about. Surface Controllers are good to post forms or render partial views, but if you click in that link that ActionLink generates you are 'getting out' of the normal Umbraco workflow.

    To work around that you can refresh the page (so you use the Umbraco workflow) but sending your category in the request. If there's not category then render all the news (or whatever), if there is then render the right category.

    You link would become:

    <a href=".?cat=currentevents">Testing</a>
    

    And the call to your controller:

    @{
        var cat = Request["cat"] ?? null;
        Html.RenderAction("RenderListOfArticles", "News", new { category = cat });
     }
    
  • Nancy A. 44 posts 175 karma points
    May 30, 2019 @ 13:11
    Nancy A.
    0

    Thank you, thank you - I tried your approach and it seems to work perfectly!

    If you could, can you elaborate when to use Surface Controllers versus RenderMvc Controllers? Would RenderMvc had worked in this instance? I tried it but got a 'No route in the route table matches the supplied values.' - would there be a suitable workaround for this scenario? Trying to understand how Umbraco works in regards to controllers/routing, this is my biggest weak area.

  • Mario Lopez 168 posts 952 karma points MVP 4x c-trib
    May 31, 2019 @ 04:18
    Mario Lopez
    1

    In both cases you need a page to render, when you try to use the RenderLink as I said before you are getting out of the Umbraco workflow. Same thing will happen with the RenderMvcController.

    The RenderMvcController is useful to hijack routes. If you check the docs about it, you can see that to instantiate the controller you need to pass a ContentModel, so you still need a 'master page' to render your content.

    Probably someone else can give you a better explanation about this, the documentation is actully pretty good. I'd never use any of those controllers for what you need.

  • Nancy A. 44 posts 175 karma points
    May 31, 2019 @ 13:31
    Nancy A.
    0

    Thanks, much appreciated!

Please Sign in or register to post replies

Write your reply to:

Draft