65

In my MVC app the controller gets the data (model) from an external API (so there is no model class being used) and passes that to the view. The data (model) has a container in which there are several objects with several fields (string values). One view iterates over each object and calls another view to draw each of them. This view iterates over the fields (string values) and draws them.

Here's where it gets tricky for me. Sometimes I want to do some special formatting on the fields (string values). I could write 20 lines of code for the formatting but then I would have to do that for each and every field and that would just be silly and oh so ugly. Instead I would like to take the field (string value), pass it to a method and get another string value back. And then do that for every field.

So, here's my question:

How do I call a method from a view?

I realize that I may be asking the wrong question here. The answer is probably that I don't, and that I should use a local model and deserialize the object that I get from the external API to my local model and then, in my local model, do the "special formatting" before I pass it to the view. But I'm hoping there is some way I can call a method from a view instead. Mostly because it seems like a lot of overhead to convert the custom object I get from the API, which in turns contains a lot of other custom objects, into local custom objects that I build. And also, I'm not sure what the best way of doing that would be.

Disclaimer: I'm aware of the similar thread "ASP.NET MVC: calling a controller method from view" (ASP.NET MVC: calling a controller method from view) but I don't see how that answers my question.

1
  • Have you tried calling the method 'normally'? You may also need to include a @using directive in your view. Commented Mar 13, 2013 at 23:10

8 Answers 8

108

This is how you call an instance method on the Controller:

@{
  ((HomeController)this.ViewContext.Controller).Method1();
}

This is how you call a static method in any class

@{
    SomeClass.Method();
}

This will work assuming the method is public and visible to the view.

Sign up to request clarification or add additional context in comments.

8 Comments

I have a similar problem but, when I try and cast to another controller I get an "Unable to cast object of type" error. the method I want is ConfigController/GetEnvironment() but, it is being called from one of my other controllers.
That syntax though. Jesus.
I don't think Jesus had anything to do with the syntax. Seriously though, the syntax is clunky because the technique is clunky. You're not really supposed to be calling controller methods from the view.
This is old, but I appreciate knowing how to call a controller method from the view. That said, I would recommend @viperguynaz helper extension suggestion and using Format() to anyone else in the OP's situation where string formatting is needed.
Hi, I have a bunch of utility/helpers classes-methods on my server side, and how can I access those classes and methods from razor views, and is there a performance penalty for doing so?
|
25

Building on Amine's answer, create a helper like:

public static class HtmlHelperExtensions
{
    public static MvcHtmlString CurrencyFormat(this HtmlHelper helper, string value)
    {
        var result = string.Format("{0:C2}", value);
        return new MvcHtmlString(result);
    }
}

in your view: use @Html.CurrencyFormat(model.value)

If you are doing simple formating like Standard Numeric Formats, then simple use string.Format() in your view like in the helper example above:

@string.Format("{0:C2}", model.value)

Comments

5

You can implement a static formatting method or an HTML helper, then use this syntax:

@using class_of_method_namespace
...
// HTML page here
@className.MethodName()

or in case of a HTML Helper:

@Html.MethodName()

Comments

3

Controller not supposed to be called from view. That's the whole idea of MVC - clear separation of concerns.

If you need to call controller from View - you are doing something wrong. Time for refactoring.

5 Comments

What if another view needs to be updated? Is there any other technique that can be used?
@TylerDurden: depends on scenario. But you always can refresh view using javascript.
Would you care to provide some example on how to do it properly, then?
This should be a comment, is an opinion, not an answer
ditto what @LeandroBardelli said. You are correct in your statement but there are always exceptions. You should have made this a comment.
2

why You don't use Ajax to

its simple and does not require page refresh and has success and error callbacks

take look at my samlpe

<a id="ResendVerificationCode" >@Resource_en.ResendVerificationCode</a>

and in JQuery

 $("#ResendVerificationCode").on("click", function() {
                getUserbyPhoneIfNotRegisterd($("#phone").val());
 });

and this is my ajax which call my controller and my controller and return object from database

function getUserbyPhoneIfNotRegisterd(userphone) {

              $.ajax({
                    type: "GET",
                    dataType: "Json",
                    url: '@Url.Action("GetUserByPhone", "User")' + '?phone=' + userphone,
                    async: false,
                    success: function(data) {
                        if (data == null || data.data == null) {
                            ErrorMessage("", "@Resource_en.YourPhoneDoesNotExistInOurDatabase");
                        } else {
                            user = data[Object.keys(data)[0]];
                                AddVereCode(user.ID);// anather Ajax call 
                                SuccessMessage("Done", "@Resource_en.VerificationCodeSentSuccessfully", "Done");
                        }
                    },
                    error: function() {
                        ErrorMessage("", '@Resource_en.ErrorOccourd');
                    }
                });
            }

1 Comment

This is ok for 99% of scenarios, but not for those the user can't stop at will.
1

You should create custom helper for just changing string format except using controller call.

Comments

1

I tried lashrah's answer and it worked after changing syntax a little bit. this is what worked for me:

@(
  ((HomeController)this.ViewContext.Controller).Method1();
)

Comments

1

You should not call a controller from the view.

Add a property to your view model, set it in the controller, and use it in the view.

Here is an example:

MyViewModel.cs:

public class MyViewModel
{   ...
    public bool ShowAdmin { get; set; }
}

MyController.cs:

public ViewResult GetAdminMenu()
    {
        MyViewModelmodel = new MyViewModel();            

        model.ShowAdmin = userHasPermission("Admin"); 

        return View(model);
    }

MyView.cshtml:

@model MyProj.ViewModels.MyViewModel


@if (@Model.ShowAdmin)
{
   <!-- admin links here-->
}

..\Views\Shared\ _Layout.cshtml:

    @using MyProj.ViewModels.Common;
....
    <div>    
        @Html.Action("GetAdminMenu", "Layout")
    </div>

2 Comments

You didn't show where to call GetAdminMenu() or is that unneccessary?
What if you need call a method from the Viewstart?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.