Zack Peterson
Zack Peterson

Reputation: 57323

How do I use a function in my ASP.NET MVC View?

I want to use a simple function like this in my ASP.NET MVC View. It takes an integer parameter and returns a string.

Function FileSizeString(ByVal ByteCount As Integer) As String
    Select Case ByteCount
        Case Is < (2 ^ 10)
            Return ByteCount.ToString("N0") + "B"
        Case (2 ^ 10) To ((2 ^ 20) - 1)
            Return (ByteCount / (2 ^ 10)).ToString("N0") + "KB"
        Case (2 ^ 20) To ((2 ^ 30) - 1)
            Return (ByteCount / (2 ^ 20)).ToString("N0") + "MB"
        Case (2 ^ 30) To Integer.MaxValue
            Return (ByteCount / (2 ^ 30)).ToString("N0") + "GB"
    End Select
End Function

I've got it in my Controller, but I cannot execute it from within my View. This produces the compile-time error "Name 'FileSizeString' is not declared."

<ul>
    <% For Each d As Document In Model.Attachments%>
    <li>
        <a href="<%=Url.RouteUrl("Download", New With {.id = a.Id}) %>">
            <%=d.FileName %> (<%=FileSizeString(d.FileSize) %> bytes)
        </a>
    </li>
    <% Next %>
</ul>

Where do I need to put my function? How do I make my View able to access it?

Upvotes: 0

Views: 4104

Answers (6)

Michael Stum
Michael Stum

Reputation: 180914

If it's specifically for this View, then it should go into the ViewModel of the View. If it's shared across multiple views, then extending HtmlHelper is one option. But adding it to the model class in question (which basically means overriding the ToString() method or adding a new one) is good if it does not return HTML but only a raw string that can be used in other parts as well.

Upvotes: 1

Zack Peterson
Zack Peterson

Reputation: 57323

I don't really care for the HtmlHelper extension suggestions. That doesn't seem appropriate for this use.

I instead added a function to the Document class:

Partial Public Class Document

    Function FileSizeString() As String
        Select Case Me.FileSize
            Case 1 To ((2 ^ 10) - 1)
                Return Me.FileSize.ToString("N0") + "B"
            Case (2 ^ 10) To ((2 ^ 20) - 1)
                Return (Me.FileSize / (2 ^ 10)).ToString("N0") + "KB"
            Case (2 ^ 20) To ((2 ^ 30) - 1)
                Return (Me.FileSize / (2 ^ 20)).ToString("N0") + "MB"
            Case (2 ^ 30) To Integer.MaxValue
                Return (Me.FileSize / (2 ^ 30)).ToString("N0") + "GB"
            Case Else
                Throw New ArgumentOutOfRangeException("byteCount", "Value must be a positive integer.")
                Return "unknown size"
        End Select
    End Function

End Class

Which I use in my ASP.NET MVC view:

<ul>
    <% For Each d As Document In Model.Attachments%>
    <li>
        <a href="<%=Url.RouteUrl("Download", New With {.id = d.Id}) %>">
            <%=d.FileName %> (<%=d.FileSizeString %>)
        </a>
    </li>
    <% Next %>
</ul>

Upvotes: 0

David Andres
David Andres

Reputation: 31781

You might want to look into Html extension methods. You can create one like this:

Public Module FileSizeExtension
  <Extension()> _
  Public Shared Function FileSizeAsString(ByVal helper AS HtmlHelper,
                                          ByVal byteCount As Integer) As String
    Select Case ByteCount  
     Case Is < (2 ^ 10)
       Return ByteCount.ToString("N0") + "B"
     Case (2 ^ 10) To ((2 ^ 20) - 1)
       Return (ByteCount / (2 ^ 10)).ToString("N0") + "KB"
     Case (2 ^ 20) To ((2 ^ 30) - 1)
       Return (ByteCount / (2 ^ 20)).ToString("N0") + "MB"
     Case (2 ^ 30) To Integer.MaxValue
       Return (ByteCount / (2 ^ 30)).ToString("N0") + "GB"
    End Select
  End Function
End Module

You can now leverage this within your views using <%= Html.FileSizeAsString(byteCount) %>

Though you can access the View's controller by means of ViewContext.Controller, you'll need to cast that property into the exact type you expect. You can then call your controller method if you like. Many people don't like this approach because it couples your View to a specific controller.

For the sake of argument, the following should work:

<% Dim homeController AS HomeController = 
    TryCast(ViewContext.Controller, HomeController) %>
<ul>
 <% For Each d As Document In Model.Attachments%>
 <li>
  <a href="<%=Url.RouteUrl("Download", New With {.id = a.Id}) %>">
   <%=d.FileName %> (<%= homeController.FileSizeString(d.FileSize) %> bytes)
  </a>
 </li>
 <% Next %>
</ul>

Upvotes: 3

ten5peed
ten5peed

Reputation: 15890

You need to make it an HtmlHelper exentsion method...

Once you've done that make sure that you import the namespace that the extenstion method is under so that your Html object in your view knows about it.

Upvotes: 1

Franci Penov
Franci Penov

Reputation: 75982

You can add it as an extension method to the HtmlHelper class. Then you can call it through the Html property of the View.

Here's an example of how to extend HtmlHelper.

Upvotes: 2

D&#39;Arcy Rittich
D&#39;Arcy Rittich

Reputation: 171371

Once you are in the view, the controller has been disposed - instead, you might make a utility class and put your method there, or make an extension method on int.

Upvotes: 1

Related Questions