【问题标题】:ASP.Net MVC: Calling a method from a viewASP.Net MVC:从视图调用方法
【发布时间】:2013-03-02 03:31:51
【问题描述】:

在我的 MVC 应用程序中,控制器从外部 API 获取数据(模型)(因此没有使用模型类)并将其传递给视图。数据(模型)有一个容器,其中有几个对象和几个字段(字符串值)。一个视图遍历每个对象并调用另一个视图来绘制它们中的每一个。此视图遍历字段(字符串值)并绘制它们。

这对我来说很棘手。有时我想对字段(字符串值)进行一些特殊的格式化。我可以为格式化编写 20 行代码,但是我必须为每个字段都这样做,这太愚蠢了,太丑了。相反,我想获取该字段(字符串值),将其传递给一个方法并返回另一个字符串值。然后对每个字段都这样做。

所以,这是我的问题:

如何从视图调用方法?

我意识到我可能在这里问错了问题。答案可能是我没有,我应该使用本地模型并将从外部 API 获得的对象反序列化为本地模型,然后在我的本地模型中,在通过之前执行“特殊格式”它的视图。但我希望有某种方法可以从视图中调用方法。主要是因为将我从 API 获得的自定义对象(又包含许多其他自定义对象)转换为我构建的本地自定义对象似乎需要很多开销。而且,我不确定最好的方法是什么。

免责声明:我知道类似的线程“ASP.NET MVC:从视图调用控制器方法”(ASP.NET MVC: calling a controller method from view),但我看不出它如何回答我的问题。

【问题讨论】:

  • 您是否尝试过“正常”调用该方法?您可能还需要在视图中包含 @using 指令。

标签: c# asp.net-mvc asp.net-mvc-4


【解决方案1】:

您不应该从视图中调用控制器。

向您的视图模型添加一个属性,在控制器中设置它,然后在视图中使用它。

这是一个例子:

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>

【讨论】:

  • 你没有显示在哪里打电话给GetAdminMenu() 或者这是不必要的?
  • 如果需要从 Viewstart 调用方法怎么办?
【解决方案2】:

我尝试了 lashrah 的答案,在稍微改变语法后它就起作用了。 这对我有用:

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

【讨论】:

    【解决方案3】:

    为什么你不用Ajax来

    它很简单,不需要page refresh 并且有success and error 回调

    看看我的样品

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

    在 JQuery 中

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

    这是我的 ajax,它调用我的控制器和我的控制器并从数据库返回对象

    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');
                        }
                    });
                }
    

    【讨论】:

    • 这适用于 99% 的场景,但不适用于用户无法随意停止的场景。
    【解决方案4】:

    控制器不应该从视图中调用。这就是 MVC 的全部理念——清晰的关注点分离。

    如果您需要从 View 调用控制器 - 您做错了。是时候重构了。

    【讨论】:

    • 如果另一个视图需要更新怎么办?有没有其他可以使用的技术?
    • @TylerDurden:取决于场景。但是您始终可以使用 javascript 刷新视图。
    • 您愿意提供一些如何正确执行此操作的示例吗?
    • 这应该是评论,是意见,不是答案
    • 同上@LeandroBardelli 所说的。您的陈述是正确的,但总是有例外。您应该对此发表评论。
    【解决方案5】:

    在 Amine 的答案的基础上,创建一个类似的助手:

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

    在你看来:使用@Html.CurrencyFormat(model.value)

    如果你正在做简单的格式化,比如Standard Numeric Formats,那么在你的视图中简单地使用string.Format(),就像上面的帮助示例一样:

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

    【讨论】:

      【解决方案6】:

      除了使用控制器调用之外,您应该创建自定义帮助器来更改字符串格式。

      【讨论】:

        【解决方案7】:

        这是你在 Controller 上调用实例方法的方式:

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

        这是在任何类中调用静态方法的方式

        @{
            SomeClass.Method();
        }
        

        假设该方法是公共的并且对视图可见,这将起作用。

        【讨论】:

        • 我遇到了类似的问题,但是当我尝试转换到另一个控制器时,我收到“无法转换类型的对象”错误。我想要的方法是 ConfigController/GetEnvironment() 但是,它是从我的其他控制器之一调用的。
        • 尽管如此。耶稣。
        • 我不认为耶稣与语法有任何关系。不过说真的,语法很笨拙,因为技术很笨拙。您实际上不应该从视图中调用控制器方法。
        • 这是旧的,但我很高兴知道如何从视图中调用控制器方法。也就是说,我会向 OP 需要字符串格式的其他任何人推荐 @viperguynaz 辅助扩展建议并使用 Format() 。
        • 嗨,我的服务器端有一堆实用程序/帮助程序类方法,我如何从 razor 视图访问这些类和方法,这样做会降低性能吗?
        【解决方案8】:

        您可以实现静态格式化方法或 HTML 助手,然后使用以下语法:

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

        或者在 HTML Helper 的情况下

        @Html.MehtodName()
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-03-22
          • 2020-11-22
          相关资源
          最近更新 更多