【问题标题】:How to create an ActionController to work both at run time and with ajax如何创建一个 ActionController 在运行时和 ajax 中工作
【发布时间】:2013-05-19 00:03:57
【问题描述】:

我有一个地址簿控制器,它将返回一个“文件夹”列表(基本上是组/位置)。这可以通过 AJAX 请求或在渲染时在 MVC 页面本身内调用。

如何创建适用于这两种情况的函数?这是我当前的控制器操作,我似乎很难在 MVC 页面中使用它

public ActionResult GetFolderList(int? parent)
{
    List<String> folderList = new List<String>();
    folderList.Add("East Midlands");
    folderList.Add("West Midlands");
    folderList.Add("South West");
    folderList.Add("North East");
    folderList.Add("North West");

    return Json(folderList);
}

在页面内(不工作 atm)

@{
    var controller = new My.Controllers.AddressBookController();
    var what = controller.GetFolderList(0);

    foreach(var p in what){
        //i want to get the list items here
    }
}

【问题讨论】:

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


    【解决方案1】:

    只要有一个返回List的函数,然后在你的页面加载和AJAX请求Action方法中调用它。

    类似:

    public List<string> GetFolderList()
    {
        List<String> folderList = new List<String>();
        folderList.Add("East Midlands");
        folderList.Add("West Midlands");
        folderList.Add("South West");
        folderList.Add("North East");
        folderList.Add("North West");
    
        return folderList;
    }
    

    然后在页面加载时,您可以将其粘贴到您的模型中:

    public ActionResult Index()
    {
        var model = new YourViewModel(); //whatever type the model is
    
        model.FolderList = GetFolderList(); //have a List<string> called FolderList on your model
    
        return View(model); //send model to your view
    }
    

    那么在你看来你可以这样做:

    @model YourViewModel
    
    @{
        foreach(var item in Model.FolderList){
            //do whatever you want
        }
    }
    

    然后,假设您的 ajax 请求类似于:

    $.ajax({
        url: '@Url.Action("GetFolders", "ControllerName")',
        type: 'POST',
        datatype: 'json',
        success: function (result) {
            for (var i = 0; i < result.length; i++)
            {
                //do whatever with result[i]
            }
        }
    });
    

    您的 GetFolders 操作方法如下所示:

    public ActionResult GetFolders()
    {
        return Json(GetFolderList());
    }
    

    【讨论】:

    • 当您从客户端进行 POST 调用时,不要忘记使用 [HttpPost] 属性装饰您的操作方法。
    • @Shyju 不以任何方式装饰它,它会接受所有动词:)
    • 你为什么要发布来获取显然应该是 GET 的方法? (它甚至还有 Get 的名字!)
    【解决方案2】:

    这将起作用:

    public ActionResult GetFolderList(int? parent)
    {
        List<String> folderList = new List<String>();
        folderList.Add("East Midlands");
        folderList.Add("West Midlands");
        folderList.Add("South West");
        folderList.Add("North East");
        folderList.Add("North West");
    
        if(Request.IsAjaxRequest())
        {
            return Json(folderList);
        }
    
        return View("someView", folderList );
    
    }
    

    【讨论】:

      【解决方案3】:

      首先,在你看来,你永远不应该做这样的事情:

      var controller = new My.Controllers.AddressBookController();
      var what = controller.GetFolderList(0);
      

      这会在视图和控制器之间产生紧密耦合,这几乎违反了 MVC 的原则。现在,回答您的问题。

      正如 mattytomo 所暗示的,您将希望使用强类型视图并从视图模型中获取您的列表。像下面这样的东西适用于简单的情况。如果这个视图变得更复杂,那么您将需要一个实际的视图模型对象:

      @model List<string>
      
      @{
        foreach (var p in Model)
        {
            p;
        }
      }
      

      现在,正如 Maris 指出的那样,您可以使用 AJAX 或普通请求的一种控制器方法以及使用 Request.IsAjaxRequest。假设您的视图名为“FolderList”,控制器操作将如下所示:

          public ActionResult GetFolderList(int? parent)
          {
              List<String> folderList = new List<String>();
              folderList.Add("East Midlands");
              folderList.Add("West Midlands");
              folderList.Add("South West");
              folderList.Add("North East");
              folderList.Add("North West");
      
              if (Request.IsAjaxRequest())
              {
                  return Json(folderList);
              }
      
              return View("FolderList", folderList);
          }
      

      现在,当您通过 AJAX 调用此方法时,它将返回 folderList 的 JSON 表示,否则它将返回您的 FolderList 视图。

      【讨论】:

        【解决方案4】:

        我曾经写过一个ActionFilter,它就是这样做的,一旦Accept http 标头包含json,它就会用JsonResult 覆盖ActionResult(并且可以通过传递@ 将自身限制为仅Ajax 请求) 987654326@ 和true):

        public class ReturnJsonIfAcceptedAttribute : ActionFilterAttribute
        {
            private bool _onAjaxOnly;
            private bool _allowJsonOnGet;
        
            public ReturnJsonIfAcceptedAttribute(bool onAjaxOnly = true, bool allowJsonOnGet = false)
            {
                _onAjaxOnly = onAjaxOnly;
                _allowJsonOnGet = allowJsonOnGet;
            }
        
            public override void OnResultExecuting(ResultExecutingContext filterContext)
            {
                var request = filterContext.HttpContext.Request;
        
                if (!_allowJsonOnGet && request.HttpMethod.ToUpper() == "GET")
                    return;
        
                var isAjax = !_onAjaxOnly || request.IsAjaxRequest();
        
                if (isAjax && request.AcceptTypes.Contains("json", StringComparer.OrdinalIgnoreCase))
                {
                    var viewResult = filterContext.Result as ViewResult;
        
                    if (viewResult == null)
                        return;
        
                    var jsonResult = new JsonResult();
                    jsonResult.Data = viewResult.Model;
        
                    filterContext.Result = jsonResult;
                }
            }
        

        然后你保持你的Action 原样,你只需附加新的ReturnJsonIfAccepted Attribute

        [ReturnJsonIfAccepted]
        public ActionResult Index()
        {
            var model = new Model(); // whatever
            return View(model);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多