I have MVC controller action which takes some model as parameter. If the model is not valid it returns JSON otherwise it returns file.
public class MainModel
{
public DownloadModel Downlaod {get;set;}
}
[ValidateAjaxRequest]
public ActionResult DownloadFile(DownloadVM model)
{
// get file using model
return File(byte[],"contenttype")
}
Note that ValidateAjaxRequest
is ActionFilterAttribute
which check if it is ajax request, and if it is then returns all errors using 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;
}
}
}
Then in javascript i am using jQuery to post the data and handle errors.
$.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
})
The reason im using ajax post instead of typical form post, is because i have some other controls on the same view which i dont want to post and also i dont want to refresh the whole view if ModelState is not valid. Something like below i DONT want to do
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
}