2
\$\begingroup\$

During a code review the following approach of delivering content conditionally dependent upon the state of the user was rejected as adverse to performance due to its multiple use of RenderAction, and instead the approach of RenderPartial was preferred. In order to take this approach it would be necessary to include conditional logic in the view, thus violating separation of concern.

What would you advise as the optimum approach for conditionally including a partial view without including logic in the view?

Header.cshtml

@Model HeaderModel

<p>Some markup</p>
@Html.RenderAction("AuthenticatedUserPanel", Model.SubModel)
@Html.RenderAction("UnauthenticatedUserPanel", Model.SubModel)

Controller.cs

Controller(IContext context)
{
     _context = context;
}

public ActionResult AuthenticatedUserPanel(Model model)
{
    if(_context.IsAuthenticated())
    {
        return View("AuthenticatedUserPanel.cshtml", model)
    }

    return EmptyContentResult();
}

public ActionResult UnauthenticatedUserPanel(Model model)
{
    if(!_context.IsAuthenticated())
    {
        return View("UnauthenticatedUserPanel.cshtml", model)
    }

    return EmptyContentResult();
}

I could possibly include the name of the target view to render in my model e.g. So that my logic for determining which view to use is contained within my ModelAdapter, but this approach feels temperamental and more error prone?

Header.cshtml

@Model HeaderModel

<p>Some markup</p>
@Html.RenderAction(Model.TheViewToRender, Model.SubModel)
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

One way you could handle this, because it's server side rendering, is perform whatever checks you wish to perform in the controller, and then route to a ViewModel that has the relevant included pages. That results in having more code to maintain, however, it enables you to have partial view rendering as well.

Edit:

I thought I would expound on this idea some. It appears to be what you are doing with the AuthenticatedUserPanel and UnauthenticatedUserPanel.

I don't see a problem with this approach. At the end of the day, you have to put this logic somewhere. Some purists may so no logic in the view. That's fine. My approach, in this situation, is to create all the necessary components, and render a different view (or ViewModel) based on some user context. The benefit to this approach is that the user can only see UI elements for actions they are able to perform, or only view data they have permission to view. It also enables you to (easily) customize the action links for subsequent navigation. The challenge I usually have with this approach is designing a view that is relevant for each type of user.

In closing, I don't see any problem with putting some of this logic in the view, but I also tend to build smaller sites. This is largely a matter of taste, and it's important to do it the same way across the project. In trying to design the way that you will handle this sort of scenario, I would consult other areas of the project that are doing it today. If there are none, then it's usually a good time to discuss with other members of the team how you will handle this case, because you will undoubtedly encounter it again.

I hope my post was helpful, and wish you the best with the project :)

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Not having enough reputation to comment is not an excuse to post an answer instead. The reputation limits exist for a reason. Use the available methods to gain enough reputation to earn the privilege to comment, by making positive contributions. That being said, this seems fine as an answer, as it gives useful insight about the code in the question. \$\endgroup\$
    – janos
    Mar 13, 2017 at 5:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.