I have a controller action which renders a partial view:
我有一个控制器动作,它呈现部分视图:
public ActionResult Details(int id)
{
DetailsViewModel model =
ModelBuilder.GetDetailsViewModel(id, _repository);
return PartialView("Details", model);
}
and I'm loading the returned content into a dynamic element as follows:
我将返回的内容加载到一个动态元素中,如下所示:
$container = appendContainer(); // adds a div to the dom with the correct id
$container.load("MyController/Details", function(response, status, xhr) {
if (status != "success") {
$(container).html('an error has occured');
}
});
so this creates a div, and then loads the returned content into that div.
这样就创建了一个div,然后将返回的内容加载到这个div中。
I want to alter this slightly so that the container div is only created if the call to the controller is succesful.
我想稍微修改一下,以便只有在对控制器的调用成功时才创建容器div。
So:
所以:
- jQuery calls the controller action
- jQuery调用控制器动作。
- controller returns PartialView, or null if Id not found
- 如果没有找到Id,控制器将返回PartialView或null
- If PartialView is returned, the container is created and loaded with the returned content.
- 如果返回了PartialView,则创建容器并装载返回的内容。
- If the controller doesn't find the Id, no content is created and an alert is displayed.
- 如果控制器没有找到Id,则不会创建任何内容并显示警报。
I'd appreciate any pointers on how I could best acheive this.
如果有什么建议,我将非常感激。
2 个解决方案
#1
11
All load
does is return HTML from a server, so why not just append to a temporary div and then get the HTML from it on success?
所有的load都是从服务器返回HTML,所以为什么不直接附加到一个临时div,然后成功地从它那里获得HTML呢?
var $dummy = $("<div>");
$dummy.load("MyController/Details", function(response, status, xhr) {
var $container = appendContainer();
if (status != "success") {
$container.html('an error has occured');
}
else
{
$container.html($dummy.html());
}
$dummy.remove();
});
UPDATE:
更新:
If you're expecting an exception then you should handle it. If you're basically allowing the error to occur just to get status != "success"
then that's a serious code smell. You should catch the error and return a different PartialView.
如果您期望出现异常,那么您应该处理它。如果您只是为了获得状态而允许错误发生,那么这是一种严重的代码味道。您应该捕获错误并返回一个不同的部分视图。
public ActionResult Details(int id)
{
try
{
DetailsViewModel model =
ModelBuilder.GetDetailsViewModel(id, _repository);
return PartialView("Details", model);
}
catch (SomeException ex)
{
return PartialView("Error", ex.Message);
}
}
Then you're guaranteed to always get a valid HTML response and if you don't, then your basic error an error occured
will come into play.
然后,您将保证始终得到有效的HTML响应,如果不这样做,那么发生的基本错误将会发挥作用。
#2
11
in your case i would use $.ajax instead of .load() gives you more control over the flow + feels more clean
在你的情况下,我会用$。ajax而不是.load()为您提供了对flow +的更多控制,使您感觉更干净
$.ajax({
url: "MyController/Details",
type: "GET",
success: function (response, status, xhr)
{
var jqContainer = appendContainer();
jqContainer.html(response);
},
error:function(XMLHttpRequest, textStatus, errorThrown)
{
//show the error somewhere - but this is a bad solution
}
});
concerning the error state - i also hate relying on exceptions - ugly and inefficient, you have several ways to handle this:
关于错误状态——我也讨厌依赖异常——丑陋而低效,您有几种方法来处理这个问题:
- return only JSON from your views and bind the returned data using some sort of templating solution, this way you can return an error object with a specific error message and handle all errors the same way(think this is the best solution).
- 仅从视图返回JSON并使用某种模板解决方案绑定返回的数据,这样就可以返回带有特定错误消息的错误对象,并以相同的方式处理所有错误(认为这是最好的解决方案)。
- return a 204 success status code -no response which is like returning null from your action - then check the status code and pop up the error message.
- 返回一个204成功的状态码——没有响应,就像从操作返回null一样——然后检查状态码并弹出错误消息。
- return a 278 success status code(not a real status code but is counts for success and lets you also send data) - here you send a json object with the error message which tou can parse and sow a nice error message (saw this 278 solution here in SO sometime ago).
- 成功返回一个278状态代码(而不是一个真正的状态代码,但成功的数量,让你也发送数据)- - -在这里你发送json对象的错误消息,或许可以解析和播种一个错误消息(看到这278解决方案在某个时候前)。
- return a different view for the error - but then you have to insert it to the container or a dummy container to check if there is an error if you want to take more actions.
- 为错误返回一个不同的视图——但是如果您想执行更多操作,则必须将其插入到容器或虚拟容器中,以检查是否存在错误。
in my code i use $(document).ajaxSend(..) to globally check all Ajax responses for 278 code and show the error messages if there is any, or call the original hooked success function.
在我的代码中,我使用$(document). ajaxsend(.. .)全局检查所有Ajax响应的278个代码,并显示错误消息(如果有的话),或者调用原始的hook success函数。
To return the error from the action i use the following result
要从操作返回错误,我使用以下结果
public class AjaxErrorWithDetailsResult : JsonResult
{
public object ErrorResult { get; set; }
public AjaxErrorWithDetailsResult(object errorResult)
{
this.ErrorResult = errorResult;
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
this.Data = ErrorResult;
context.HttpContext.Response.StatusCode = 278;
base.ExecuteResult(context);
}
}
where ErrorResult can be an anonymous object or an object that implement an interface with a property of ErrorMessage so you will know what to look for at the JS
ErrorResult可以是一个匿名对象,也可以是一个实现带有ErrorMessage属性的接口的对象,这样您就知道在JS中应该查找什么了
#1
11
All load
does is return HTML from a server, so why not just append to a temporary div and then get the HTML from it on success?
所有的load都是从服务器返回HTML,所以为什么不直接附加到一个临时div,然后成功地从它那里获得HTML呢?
var $dummy = $("<div>");
$dummy.load("MyController/Details", function(response, status, xhr) {
var $container = appendContainer();
if (status != "success") {
$container.html('an error has occured');
}
else
{
$container.html($dummy.html());
}
$dummy.remove();
});
UPDATE:
更新:
If you're expecting an exception then you should handle it. If you're basically allowing the error to occur just to get status != "success"
then that's a serious code smell. You should catch the error and return a different PartialView.
如果您期望出现异常,那么您应该处理它。如果您只是为了获得状态而允许错误发生,那么这是一种严重的代码味道。您应该捕获错误并返回一个不同的部分视图。
public ActionResult Details(int id)
{
try
{
DetailsViewModel model =
ModelBuilder.GetDetailsViewModel(id, _repository);
return PartialView("Details", model);
}
catch (SomeException ex)
{
return PartialView("Error", ex.Message);
}
}
Then you're guaranteed to always get a valid HTML response and if you don't, then your basic error an error occured
will come into play.
然后,您将保证始终得到有效的HTML响应,如果不这样做,那么发生的基本错误将会发挥作用。
#2
11
in your case i would use $.ajax instead of .load() gives you more control over the flow + feels more clean
在你的情况下,我会用$。ajax而不是.load()为您提供了对flow +的更多控制,使您感觉更干净
$.ajax({
url: "MyController/Details",
type: "GET",
success: function (response, status, xhr)
{
var jqContainer = appendContainer();
jqContainer.html(response);
},
error:function(XMLHttpRequest, textStatus, errorThrown)
{
//show the error somewhere - but this is a bad solution
}
});
concerning the error state - i also hate relying on exceptions - ugly and inefficient, you have several ways to handle this:
关于错误状态——我也讨厌依赖异常——丑陋而低效,您有几种方法来处理这个问题:
- return only JSON from your views and bind the returned data using some sort of templating solution, this way you can return an error object with a specific error message and handle all errors the same way(think this is the best solution).
- 仅从视图返回JSON并使用某种模板解决方案绑定返回的数据,这样就可以返回带有特定错误消息的错误对象,并以相同的方式处理所有错误(认为这是最好的解决方案)。
- return a 204 success status code -no response which is like returning null from your action - then check the status code and pop up the error message.
- 返回一个204成功的状态码——没有响应,就像从操作返回null一样——然后检查状态码并弹出错误消息。
- return a 278 success status code(not a real status code but is counts for success and lets you also send data) - here you send a json object with the error message which tou can parse and sow a nice error message (saw this 278 solution here in SO sometime ago).
- 成功返回一个278状态代码(而不是一个真正的状态代码,但成功的数量,让你也发送数据)- - -在这里你发送json对象的错误消息,或许可以解析和播种一个错误消息(看到这278解决方案在某个时候前)。
- return a different view for the error - but then you have to insert it to the container or a dummy container to check if there is an error if you want to take more actions.
- 为错误返回一个不同的视图——但是如果您想执行更多操作,则必须将其插入到容器或虚拟容器中,以检查是否存在错误。
in my code i use $(document).ajaxSend(..) to globally check all Ajax responses for 278 code and show the error messages if there is any, or call the original hooked success function.
在我的代码中,我使用$(document). ajaxsend(.. .)全局检查所有Ajax响应的278个代码,并显示错误消息(如果有的话),或者调用原始的hook success函数。
To return the error from the action i use the following result
要从操作返回错误,我使用以下结果
public class AjaxErrorWithDetailsResult : JsonResult
{
public object ErrorResult { get; set; }
public AjaxErrorWithDetailsResult(object errorResult)
{
this.ErrorResult = errorResult;
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
this.Data = ErrorResult;
context.HttpContext.Response.StatusCode = 278;
base.ExecuteResult(context);
}
}
where ErrorResult can be an anonymous object or an object that implement an interface with a property of ErrorMessage so you will know what to look for at the JS
ErrorResult可以是一个匿名对象,也可以是一个实现带有ErrorMessage属性的接口的对象,这样您就知道在JS中应该查找什么了