"if" considered harmful in ASP.NET MVC View (.aspx) files? - asp.net-mvc

I remember seeing a blog (or something) that said you should not use <% if ... %> in .aspx files in ASP.NET MVC, but I can't remember what it said the alternative is. Can anyone remember seeing this and point me to it?

Basically what it means is that you shouldn't have huge if statements in your Views, your Controllers and ViewModels should be able to handle the logic. Example:
<h2 class="title">
<% if (ViewData["category"] == null { %>
All Products
<% } else { % >
<%= ViewData["category"] %>
<% } %>
</h2>
Should be:
<h2 class="title>
<%= Model.Title %>
</h2>
If your controllers and ViewModels can't handle the logic, you should write Html Helpers for more complicated logic (thus making it reusable and more readable).
<h2 class="title>
<%= Html.GetPageTitle(Model.Category) %>
</h2>

I think what you're referring to is a post by Rob Conery, where he mentions a rule he uses:
If there's an if, make a helper
So to answer your question, the idea is that if you find yourself needing to use if in your View, you should consider adding a helper extension method to render that part of your View instead.

I'm not sure if this is what you saw, but here is a blog that mentions it. See item #11.

As i think the best approach for this is try to handle your if condition in controller and pass the specific view for required result or pass the View name in a variable to render.
public class HomeController :Controller
{
public ActionResult Category(string? category)
{
View viewToReturn;
if (category == null)
viewToReturn = View("CategoryList", repo.GetAllCategory); /// it is a View
else
viewToReturn = View("Category", repo.GetCategory(category)); /// it is a View
return viewToReturn;
}
}
Well, Martin answer is also from best practices.

I feel that is just fine. It allows for the view to have control of its presentation.

I suspect that the point was an attempt to avoid spaghetti code rather than restrict the use of "if"s, here is a link to a Rob Conery blog about this, he does actually mention using helpers instead of Ifs so this may be what you saw ASP.NET MVC: Avoiding Tag Soup

Is this the issue you're referring to?
binding expressions can not be used in statement block <% %>, just as
statements can not be used in a binding expression block <%# %>
-- bruce (sqlwork.com)
"Jason" <> wrote in message
news:23C11F83-A2AA-406D-BDEC-...
What is wrong with the following if statement in my aspx page?
"T" Then%>
I get error that says: BC30201: Expression expected.
Bruce Barker

Related

Rails + Show Dynamic content with backbone.js

I'm making an API call using backbone model that returns JSON with list of posts.
Each post is dynamic as it can be
1. liked or unliked
2. commented or not commented
3. Shared with Public or private or a group
Now in my backbone template while displaying the posts, I'm doing a if else conditions to display the dynamic content.
<% if(jsonresponse["like"] == true){ *>
Like
<%} else %>
Unlike
<% } %>
<% if(jsonresponse.target == 'public'){ *>
Public
<%} else if(jsonresponse.target == 'private'){%>
Private
<% } else if(jsonresponse.target == 'groups'){%>
<%= post.target.shared[0].displayName %>
<% } %>
Is this how we should display dynamic content?
Checking conditions in a template is the right way to do it?
I know it looks a bit ugly but there isn't anything wrong with it. Maybe you could split up your view into two (like/unlike ... public/private/groups) so that when user clicks on like/unlike you only render the above view.
In Handlebars, which I use, we tend to write helpers functions which abstracts these if/else and makes the view all clean. That's one option but it's a bit overkill if you only have this one situation

ASP.NET MVC: shortcut for Response.Write and String.Format

I've found a pattern in my Views like this:
<% if (someCondition)
{
Response.Write(string.Format("Foo {0}, Bar {1} Baz {2}.", userName, someCounter, someDate)); }
else
{
Response.Write(string.Format("Foo is {0}.", bar));
}
%>
The basic pattern of if...else with a bunch of repeated Response.Write(string.Format()) for each condition. The idea here is not re-usability in where a partial view or helper method would be appropriate, but rather a shortcut that would ideally look like Response.WriteFormattedString().
The question here is around DRY and Response.Write(string.Format()). Are there better, or more concise ways to . Consider that HTML encoding would be a nice feature to include, perhaps as a boolean to a method call of some kind (extension method on Html?.
The goal is to try to avoid multiple render blocks <%: %> and <%= %>.
Is there an obvious extension method that I'm missing?
Do you have an extension method that you rely on to achieve this functionality?
<%: Html.Greeting(Model) %>
...Where Html.Greeting is a method you write which accepts your page model.

Should I use Response.Write directly from a View?

I have been trying to avoid using Response.Write(...) directly in my MVC Views. The reason being that I just need to type the string literals and the view engine knows what to do. However, in certain circumstances I seem to be creating way too many pointy brackets (<% %>). So, which of these 2 code snippets do you find more acceptable?
<% if (true)
{
Response.Write(Model.SomeValue);
} %>
Or
<% if (true) { %>
<%= Model.SomeValue %>
<% } %>
This is why Html Helpers exist (to avoid spaghetti code as much as possible):
<%= Html.MySuperHelper(Model.SomeValue) %>
Every time you need write an if statement in a view you might ask yourself the question: wouldn't it be better to write a helper method (which as a bonus could be unit tested) instead?
How about a third possibility?
<%= condition ? Html.Encode(Model.SomeValue) : "" %>
Although in practice you should keep all but the very simplest logic out of your view altogether. Either do the work in your controller or wrap the logic up in a HTML helper of some kind.
Or a fourth:
<%= condition ? Html.Encode(Model.SomeValue) : "" %>

VB Syntax to declare a single model in MVC (to leverage strongly typed views)

I'm trying to avoid the use of magic strings as much as I can, but I can't find the correct syntax for VB to bind a single model like is shown in this c# example.
Can anyone point me in the right direction?
(currently the below says "expected end of statement" under the Model text)
<% Dim FormObject As Form = (Form)Model %>
EDIT:
A simple directcast was need (sorry for the dumb question)
<% Dim FormObject As Form = DirectCast(Model, Form)%>
What you're trying to port is a cast operator. Try the following code.
<% Dim FormObject As Form = DirectCast(Model, Form) %>
you have to make your view strongly typed like this either you use C# or VB.NET:
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage<FormObject>" %>
so that when you want to use it you don't need to cast it
<% Dim FormObject As Form = Model %>

Child records not posting on ASP.NET MVC form

I have two tables, Author and Book, where an author can have many books. I've got an edit view set up as "System.Web.Mvc.ViewPage(of MyDatabase.Author)". The form is set up to show the Author and all his books, with the ability to edit book information:
<% Using Html.BeginForm()%>
<%=Model.author_name%> <br/>
<% For Each item In Model.Books%>
<%=Html.CheckBox("checked_out")%>
<%=item.book_name%> <br/>
<% Next%>
<input type="submit" value="Save" />
<% End Using%>
In the controller, I've got the Post function:
<ActionName("Edit"), AcceptVerbs(HttpVerbs.Post)> _
Function Save(ByVal form As Author) As ActionResult
Dim book_count = Author.Books.Count
End Function
The problem is that the Books collection isn't part of the post - book_count is zero, even though there are several books displayed.
Am I doing something wrong, or am I expecting too much in the post? How can I make this work?
I believe your problem is that the "magic parser" for MVC has nothing to hang it's hat on. When you put items on your page that you want to be able to grab back on the post that are enumerated inside of a collection, you've got to give your "things" names. So, what I did in my page is if I didn't want them to be able to edit a field, like your book name above, I would use a hidden field to wrap the value up in a control that MVC can get at via magic and then also display that value to the user. So, it could look something like:
<% for (i = 0; i < Model.Books.Count; i++) {
book = Model.Books[i] as book //I'm a C# guy so make this VB
<%= Html.CheckBox("author["+1+"].checked_out", book.checked_out) %>
<%= HtmlHidden("author["+i+"].book_name",book.book_name) %>
<%= book.book_name %>
<% } %>
...and then this should come back all nicely packaged for you as a book collection in your Authors object. See if that gets you in the right direction.
EDIT
One other thought too. I'm using the UpdateModel method to fetch the results. It shouldn't matter, but I thought I'd throw that in there.
See here for the full answer to this problem. I basically didn't grok how MVC wanted the variables to be named.

Resources