我无法确定AJAX调用的控制器操作是应返回部分视图还是“原始”JSON。
返回部分视图,使用呈现的HTML使javascript更容易使用返回的HTML更新当前DOM。但是,它确实限制了使用Web服务的javascript客户端可以对返回的HTML执行的操作。
另一方面,让控制器操作返回JSON将需要javascript调用“手动”根据返回的JSON创建标记。
与往常一样,每种方法都有它的好处和缺点。每种方法都有其他优点/缺点吗?
答案 0 :(得分:18)
在我看来,返回JSON然后让客户端查看排序可能会因为以下限制而变得混乱:
我处理这个的方法是返回渲染的HTML,但是使用局部视图返回这个渲染的HTML。这为您提供了两全其美的体验。您已获得服务器端模板以及IntelliSense支持。
以下是一个例子:
这是我的Ajax调用,因为你可以看到它所做的就是替换我的无序列表的html:
FilterRequests: function() {
$.post("/Request.aspx/GetFilteredRequests", { }, function(data) {
$('ul.requests').html(data);
});
},
这是我在我的控制器上的动作:
public ActionResult GetFilteredRequests(string filterJson)
{
var requests = _requestDao.LoadAll();
return PartialView("FilteredRequests", requests);
}
最后这是我的部分视图(没有必要理解这一点,我只是向您展示一些渲染在真实世界的应用程序中会有多复杂。我很害怕在JavaScript中这样做。你也会注意到我的局部视图反过来调用其他部分视图。):
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Request>>" %>
<%@ Import Namespace="Diangy.HelpDesk.Models.Lookups"%>
<%@ Import Namespace="Diangy.HelpDesk.Models.Requests"%>
<%@ Import Namespace="System.Web.Mvc.Html"%>
<% foreach (var request in ViewData.Model) %>
<%{%>
<li class="request">
<h2>#<%= request.Id %>: <%= request.InitialInteraction().Description %></h2>
<p>from <%= request.Customer.FullName %> (<%= request.Customer.EmailAddress %>), <%= request.InitialInteraction().UsableTimeStamp %></p>
<h3>Custom Fields & Lookups</h3>
<div class="tabs">
<ul>
<li><a href="#customfields<%= request.Id %>">Custom Fields</a></li>
<% foreach (var lookupDefinition in (List<LookupDefinition>)ViewData["LookupDefinitions"]) %>
<%{%>
<li><a href="#<%= lookupDefinition.Name.ToLowerInvariant().Replace(" ", "") + request.Id %>"><%= lookupDefinition.Name %></a></li>
<%}%>
</ul>
<% Html.RenderPartial("CustomFields", request); %>
</div>
<% Html.RenderPartial("Discussion", request); %>
<% Html.RenderPartial("Attachment", request); %>
</li>
<%}%>
答案 1 :(得分:16)
如果您正在使用MVC范例,则控制器应返回数据(JSON)并让视图自行对其进行排序,就像它的工作是查找/调整模型中的数据并将其传递给视图一样在服务器端。
你得分为褐色
保持逻辑和UI之间关注点的分离
使你的ajax动作可测试(祝你好运测试从该动作返回的HTML ......)
它可能有点复杂,但它适合。
您可以使用客户端模板系统(例如MS Ajax Toolkit中现有的系统)来帮助消除部分负载并在客户端保留逻辑/呈现分离。
所以我肯定会说JSON。但是,嘿,YMMV像往常一样......
答案 2 :(得分:4)
我想允许调用应用程序来决定。我把MultiViewController(我在网上发现的大部分代码,我会在找到它的时候尝试用信用卡更新)加在一起,基于动作扩展,它将返回相应的格式。例如:
myapp.com/api/Users/1 - defaults to html based on route
myapp.com/api/Users.html/1 - html
myapp.com/api/Users.json/1 - json
myapp.com/api/Users.xml/1 - xml
myapp.com/api/Users.partial/1 - returns a partial view of action name (see code)
myapp.com/api/Users.clean/1 - partial html without styling, etc...
我的控制器继承自MultiViewController而不是“return view(Model);”我只是调用“返回FormatView(Model);或者FormatView(”ViewName“,Model);”。第二个是如果我需要将特定视图应用于结果 - 而不是隐含视图。
MultiViewController看起来像这样。特别注意FormatView,whitch返回一个动作结果:
public abstract class MultiViewController : Controller
{
private const string FORMAT_KEY = "format";
public enum FileFormat {Html, Json, Xml, Partial, Clean}
protected MultiViewController()
{
RequestedFormat = FileFormat.Html;
}
protected FileFormat RequestedFormat { get; private set; }
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
var routeValues = filterContext.RouteData.Values;
if (routeValues.ContainsKey(FORMAT_KEY))
{
var requestedFormat = routeValues[FORMAT_KEY].ToString();
if (isValidFormat(requestedFormat))
{
RequestedFormat = (FileFormat)Enum.Parse(typeof(FileFormat), requestedFormat, true);
}
}
}
private bool isValidFormat(string requestedFormat)
{
return Enum.GetNames(typeof (FileFormat)).Any(format => format.ToLower() == requestedFormat.ToLower());
}
protected ActionResult FormatView(string viewName, object viewModel)
{
switch (RequestedFormat)
{
case FileFormat.Html:
if (viewName != string.Empty)
{
return View(viewName,viewModel);
}
return View(viewModel);
case FileFormat.Json:
return Json(viewModel);
case FileFormat.Xml:
return new XmlResult(viewModel);
case FileFormat.Partial:
//return View(this.ControllerContext.RouteData.Values["action"] + "Partial");
return PartialView(this.ControllerContext.RouteData.Values["action"] + "Partial");
case FileFormat.Clean:
if (viewName != string.Empty)
{
return View(viewName, "~/Views/Shared/Clean.master", viewModel);
}
var v = View(viewModel);
v.MasterName = "~/Views/Shared/Clean.Master";
return v;
default:
throw new FormatException(string.Concat("Cannot server the content in the request format: ", RequestedFormat));
}
}
protected ActionResult FormatView(object viewModel)
{
return FormatView("", viewModel);
}
}
Clean.master只是一个不包含任何其他html的母版页 - 它接受视图(这样我可以合并任何部分类)并使用可以直接放置的干净html呈现它。
如果我想要json - 控制器构建我的viewmodel然后将该视图模型作为json返回,而不是发送到默认视图 - 与.xml相同。
部分视图有点有趣,按照惯例,我的所有主视图都被分解为部分视图,因此可以自己请求特定的部分 - 这对于使用jquery模拟updatepanel的功能非常方便所有与updatepanel相关的垃圾。
答案 3 :(得分:2)
为了保持关注点的分离,你应该返回JSON。
当您返回html时,您可以限制使用返回的数据执行的操作。如果您需要一个数据列表并希望以不同的方式呈现它,请使用JSON,否则您必须在服务器上使用不同的方法来获取相同数据的不同呈现。
答案 4 :(得分:2)
为什么不同时使用json和html? 在当前项目中我们正在制作路线,因此您可以从前端进行选择,在某些情况下哪种格式最适合...所以为什么不制作两个控制器,首先将返回json中的预期数据,另一个控制器将返回相同的数据,但与HTML ...这样你可以选择让我们说jQuery什么时候你想要什么,你想要它的格式......最好的是,对于不同的格式你只需要调用不同的地址...
换句话说,让它安静下来,宝贝! :)欢呼声
答案 5 :(得分:2)
至于我,我选择数据驱动的方法。以下是两个小功能:
数据驱动:
HTML驱动:
所以你可以使用HTML驱动的方法维护MVC,虽然它会有点难度。
答案 6 :(得分:0)
如果您使用JQuery,您应该使用JSON或XML,因为它更容易修改,但如果您的ajax调用仅返回列表框的项目,例如您也可以使用html。
我的个人偏好是JSON或XML,因为经常使用JQuery