I am currently working on converting an existing webforms application to MVC and am not sure how to design one of the pages. The existing page is 2500 lines of code, and is responsible for displaying several different views of the same information. The following example is just a small piece of this page (a toolbar), but I'm not sure what the best approach is to avoid duplicating code.
Administrator view toolbar: Save, PDF, Print, Spell Check, Administrative Documents, Employee View Toggle
Manager view of toolbar: Save, PDF, Print, Spell Check, Employee View Toggle
Employee view of toolbar: Save, PDF, Print, Spell Check
I have split the application into three different views. They use the same partial views to render the content of the page, but currently each view has it's own copy of the toolbar. So the HTML elements for Save, PDF, Print and Spell Check are duplicated in each of the views. It would be ideal to have a partial view to render the toolbar, but in order to do that I would need to put some sort of logic in the view to determine if it should show the Employee View Toggle link or the Administrative Documents.
I have also ran into similar problems while developing other new pages. Initially the requirements for different pages have the same element on them that we split into a partial view. After testing and adding more functionality, eventually the partial view needs to be slightly different on each of the pages. Usually it's just the visibility of the certain controls, but eventually the partial views end up having a bunch of logic in them to check several things to determine if something should be shown.
What is the best approach for dealing with slightly different views where most of the elements are the same?
If it's just an issue of permissions showing or hiding different parts of the same control/partial view/whatever, I would say just write one and have some code in it to check permissions and conditionally render or don't render various parts. Something like this:
<%@ Control Language="C#" %>
This is the toolbar!!
<div class="fake-css-class">
<%:Html.ActionLink("Save", "Save") %>
<%:Html.ActionLink("PDF", "Pdf") %>
<%:Html.ActionLink("Spell Check", "SpellCheck") %>
<% if (CurrentUser.IsInRole("Admin") { %>
<%: Html.ActionLink("Administrative Documents", "AdminDocs") %>
<%} %>
<% if (CurrentUser.IsInRole("Admin") || CurrentUser.IsInRole("Manager"){
%>
<%: Html.ActionLink("Employee View Toggle", "EmpView") %>
<%} %>
</div>
<br />
<br />
EDIT:
When the logic gets more complicated, add functions to your security code so that you can separate all the logic out into your model/controller and in the view you're making a single function call. For example something like this:
public bool Authorize(string controllerName, string actionName) {
bool authorize = false;
foreach(var permission in this.permissions) {
if (permission.Matches(controllerName, actionName)) {
authorize = permission.Affirmative;
}
}
return authorize;
}
This way you could have the code outside of the view and simply a single line of code in the view. The above code is just taken out of my current project and used as an example, but you can write whatever complicated logic and put it out in the model or controller so your view stays clean and you aren't putting business logic in there.