1

モデルをパラメーターとして受け取る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それがajaxリクエストであるかどうかを確認し、そうである場合はActionFilterAttributeJsonを使用してすべてのエラーを返すことに注意してください

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
}
4

0 に答える 0