ETFairfax
ETFairfax

Reputation: 3814

Avoiding spaghetti code in ASP.NET MVC

Probably a stupid question, but here goes. In my view, I have the following code....

   <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Learner.MvcApplication.ViewModels.PagerViewModel>" %><% 

for (int i = Model.StartPage; i <= Model.EndPage; i++)
{
    %>
    <% =Html.Label(ViewData.Model.Controller + i.ToString()) %>
    <%
} %> 

Do I have to close and reopen around the call to Html.Label "%><%" etc.?

I'd much rather do something like...

for (int i = Model.StartPage; i <= Model.EndPage; i++)
{
    Html.Label(ViewData.Model.Controller + i.ToString());
} 

...but the labels aren't being displayed.

Can you guess that I'm new to this??

Many thanks,

ETFairfax.

Upvotes: 9

Views: 1576

Answers (6)

Phil Strong
Phil Strong

Reputation: 1014

Also consider a switch to Razor view engine. You can get rid of those pesky <% %>

for (int i = Model.StartPage; i <= Model.EndPage; i++)
{
    %>
    <% =Html.Label(ViewData.Model.Controller + i.ToString()) %>
    <%
} %>

becomes

@for (int i = Model.StartPage; i <= Model.EndPage; i++)
{        
    Html.Label(ViewData.Model.Controller + i.ToString())        
}

Upvotes: 2

Darin Dimitrov
Darin Dimitrov

Reputation: 1039498

<%=x %> is just a shortcut for Response.Write(x):

for (int i = Model.StartPage; i <= Model.EndPage; i++)
{
    Response.Write(Html.Label(ViewData.Model.Controller + i.ToString()));
}

Upvotes: 26

Charles Ouellet
Charles Ouellet

Reputation: 6508

Another suggestion is to create a custom HtmlHelper that would take the Start and EndPage as parameters. In the Helper you should do something like this:

 public static string Pager<TModel>(this HtmlHelper<TModel> html, Func<TModel, string> Prefix, int StartPage, int EndPage) where TModel : class
    {
        var builder = new StringBuilder();

        for (var i = StartPage; i <= EndPage; i++)
            builder.Append(html.Label(Prefix.Invoke(html.ViewData.Model) + i));

        return builder.ToString();
    }

Test (note that I am using MvcContrib TestControllerBuilder and RhinoMocks :

[Test]
        public void Pager_should_be_ok()
        {
            var testBuilder = new TestControllerBuilder();
            var controller = new TestController();

            testBuilder.InitializeController(controller);

            var viewData = MockRepository.GenerateStub<IViewDataContainer>();
            viewData.ViewData = new ViewDataDictionary
            {
                Model = new TestObject { Key = "Test", Value = "Value" }
            };

            var viewContext = new ViewContext { RouteData = new RouteData(), RequestContext = controller.ControllerContext.RequestContext };
            var html = new HtmlHelper<TestObject>(viewContext, viewData);

            var output = html.Pager(x => x.Key, 1, 2);

            Assert.That(output, Is.EqualTo("Test1Test2"));
        }

Then in your view you can use this like that:

<%= Html.Pager(x => x.Controller, Model.StartPage, Model.EndPage) %>

So this is avoiding the spaghetti code that you don't want to see and this is testable.

Upvotes: 0

AnthonyWJones
AnthonyWJones

Reputation: 189555

The correct answer has already been given (at least twice). However some subtlies are worth pointing out. Fundementally,

<% stuff here %>

means execute the contained statements represented by "stuff here" using the default language. Whereas:-

<%=stuff here %>

means evaluate the contained string expression represented by "stuff here" using the default language and send the result to the response.

Here is a common gotcha. Is this:-

<%="Hello, World!"%>

the same as this:-

<%Response.Write("Hello, World!")%>

?

Ans: no. Note the first is an expression and is not terminated with a ;. Whereas the second is a statement and will be a syntax error. It has the ; missing.

Upvotes: 3

Rohith
Rohith

Reputation: 2091

The key here is to understand the difference between <% some code %> and <%= some code %>. <% some code %> means just execute "some code". <%= some code %> means execute some code and put the return value in the response. This is why Darin's answer above works by using Response.Write.

Upvotes: 4

Filip Ekberg
Filip Ekberg

Reputation: 36327

This is just a short-tag <%= for <% Response.Write note the difference between <% and <%=

So you could very well write it like this:

for (int i = Model.StartPage; i <= Model.EndPage; i++)
{
    Response.Write(Html.Label(ViewData.Model.Controller + i.ToString()));
}

One could argue which is nicer..

Upvotes: 6

Related Questions