我有 MVC 控制器动作,它以一些模型作为参数。如果模型无效,则返回 JSON,否则返回文件。
public class MainModel
{
public DownloadModel Downlaod {get;set;}
}
[ValidateAjaxRequest]
public ActionResult DownloadFile(DownloadVM model)
{
// get file using model
return File(byte[],"contenttype")
}
请注意,这ValidateAjaxRequest
是ActionFilterAttribute
检查它是否是 ajax 请求,如果是则使用 Json 返回所有错误
public class ValidateAjaxRequestAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.HttpContext.Request.IsAjaxRequest())
return;
var modelState = filterContext.Controller.ViewData.ModelState;
if (!modelState.IsValid)
{
var errors = new List<MyStatus>();
//loop through all errors here and build errors list
filterContext.Result = new JsonResult()
{
Data = errors
};
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
}
}
}
然后在 javascript 中,我使用 jQuery 发布数据并处理错误。
$.ajax({
type: "POST",
data: $('#formid').serialize(),
url: '/Home/DownloadFile'
})
.done(function (response, textStatus, jqXHR)
{
// how do i show file here as popup?
}
.fail(function (jqXHR, textStatus, errorThrown) {
//show returned errors from the server
})
我使用 ajax 发布而不是典型的表单发布的原因是因为我在同一个视图上有一些其他控件,我不想发布,而且如果 ModelState 无效,我也不想刷新整个视图。像下面这样的事情我不想做
public ActionResult DownloadFile(MainModel model)
{
if(ModelState.IsValid)
{
// get file using model.Download
return File(byte[],"contenttype")
}
return View("Index",model)
// here i have to post entire MainModel and also re-render
// entire View if ModelState is not valid.
// i do not like this approach so im using ajax to post only
// what i needed and without needing to re-render view
}