tags:

views:

56

answers:

3

I have a web application I'm working on, and I'd like to avoid the clutter of if/elseif/else in the view, and of having way too many separate ascx files just for conditional inclusion in a view.

What I want to do is create some sort of simple class that works like so (an example will demonstrate what I'd like to achieve)

<% using(RequiresAccessTo.Feature(Features.FancyStuff)) { %>
Special content for users
<% } %>

If the user does not have access to the feature, the class would render a sign up link instead. I know I could simply use if/else, but the content of the else block could be one of 2-3 different standard responses depending on access level, and this mechanism would be used in countless places around the website.

If there a way to simply prevent Special content for users from rendering altogether, it'll mean I can make the templates around the website really easy to maintain.

+1  A: 

I can think of one other decent option to keeping your if/else logic in a partial view.

You could create an HtmlHelper extension method. HtmlHelper is the object used when calling things like Html.ActionLink in a view. You can write your own method that produces whatever HTML you want. The conditionals all take place in the extension method and your view code is reduced to:

<%= Html.MyControl(param1, param2) %>

The rule of thumb I follow when deciding when to create an HtmlHelper extension method and when to create a partial view is generally how much HTML is going to be generated. If I end up with more than a few lines of rendered HTML, a partial control is generally your best bet as it is generally easier to understand and maintain the HTML.

If you're worried about organizing numerous partial views, you can create subfolders under your Shared view directory. The views can then be referenced like this:

<% Html.RenderPartial("Subfolder/PartialView") %>
Chuck
Thanks, I've considered all those methods though. The issue is that single views will get split into multitudes of different partial views. The one I'm working on alone would have 20-30 ascx files just for itself. The point was to basically be able to wrap any arbitrary small chunk of content and have it substituted for something else if a standard site-wide set of conditions is not met.
Nathan Ridley
... so the controls wouldn't be reused anywhere anywhere and partials would just end up cluttering your project. Let me try again, different answer...
Chuck
A: 

I just thought of an alternative solution:

<% if(!BlockContentAndRenderPlaceHolder(Feature.Whatever)) { %>
whatever
<% } %>

I know it looks a bit obtuse, but if you saw the content on these pages, you'd understand.

Nathan Ridley
+2  A: 

Another option you might try would be to create a custom server control. Properties on the control could include the feature set you'd want to check permission for. If that permission wasn't met, the control would render the sign up link appropriate for that access level or permission. Your view would end up looking something like:

<controls:SignUpWrapper runat="server" id="signup" access="FancyStuff">
    <div>
        Approved user contents.
    </div>
</controls:SignUpWrapper>

In your control, you would first check permission then render either the appropriate link or the provided HTML. The trickiest bit here might be getting the routing information to your server control code. Not something I've tried. Worst case scenario I imagine you should be able to pass the necessary information or even the entire sign up link through properties. No wait, worse would be bypassing routing altogether and forcing the URL in through a configuration value, erm... yeah. Either way it's a bit wordier than your desired example, but not far off.

I suppose some folk might see even the server control idea as a bit wonky. But as long as you stay away from view state, post back behavior and maybe a few other classic ASP.NET features, there's nothing preventing using server controls. We all use masters and content containers already. Sorry to preach if you're already in the choir. =)

For the time being, this is stretching my imagination and maybe even common sense a bit depending on the difficulty of generating that link. I'll check back if I think of anything else.

Chuck
Hmm, that could work. Falling back on ASP.Net WebForms syntax irks me a bit though. The whole problem could be solved if there was a way to suppress Response.Write output temporarily.
Nathan Ridley
I suppose the problem is that the logic needs to go somewhere and at this point we're just talking about pretty ways to do that. I once looked into trying to create my own 'using' friendly entity/routine for MVC similar to the Html.BeginForm() mechanism. I think what I found is that there is a special consideration in the page for that. Would be nice to be able to write our own though.
Chuck
I'm going to mark this as correct because basically this is the best answer for now.
Nathan Ridley