ASP.NET MVC 3 RazorでのAjax.BeginFormの使用


264

Ajax.BeginForm控えめな検証とAjaxが存在するAsp.net MVC 3内で使用するチュートリアルまたはコード例はありますか?

これはMVC 3のとらえどころのないトピックであり、フォームを適切に機能させることができないようです。Ajax送信を行いますが、検証エラーを無視します。

回答:


427

例:

モデル:

public class MyViewModel
{
    [Required]
    public string Foo { get; set; }
}

コントローラ:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel());
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return Content("Thanks", "text/html");
    }
}

見る:

@model AppName.Models.MyViewModel

<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>

<div id="result"></div>

@using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "result" }))
{
    @Html.EditorFor(x => x.Foo)
    @Html.ValidationMessageFor(x => x.Foo)
    <input type="submit" value="OK" />
}

そして、これが(私の観点では)より良い例です:

見る:

@model AppName.Models.MyViewModel

<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/index.js")" type="text/javascript"></script>

<div id="result"></div>

@using (Html.BeginForm())
{
    @Html.EditorFor(x => x.Foo)
    @Html.ValidationMessageFor(x => x.Foo)
    <input type="submit" value="OK" />
}

index.js

$(function () {
    $('form').submit(function () {
        if ($(this).valid()) {
            $.ajax({
                url: this.action,
                type: this.method,
                data: $(this).serialize(),
                success: function (result) {
                    $('#result').html(result);
                }
            });
        }
        return false;
    });
});

jQueryフォームプラグインでさらに拡張できます


41
AjaxでjQUeryを使用することに同意します。Asp.net MVC Ajaxアプリケーションの大部分は、組み込みのAjax拡張機能ではなくjQueryを使用していると思います。
Robert Koritnik

6
私は次のようなものを使用していますが、結果はdiv結果を単に置き換えるのではなく、独自のページに移動するようです。なぜなのかご存知ですか?
デビッド

3
はい、私もajaxに純粋なjQueryを使用することに同意します。MVCajax拡張機能を使用すると、最終的にjQueryを使用するために他のルールや構文を不必要に学習する必要があることを意味します。だから私はもっと書く必要がありますが、正しい方法で書くほうがいいですし、あなたはより多くの制御と柔軟性を得ます。
Nestor

3
@ darin-dimitrov:後者の例を試すときは、データを追加する必要があります:$( 'form')。serialize()、ajax()呼び出し。そうしないと、フォームデータが渡されず、サーバー側でモデルが無効になります。私が見落としているものがあるのだろうか?
Brett

2
@DarinDimitrov BLLにエラーがあり、モデルをビューに送り返してエラーメッセージを表示する必要がある場合は、ハードレイヤーがデータに対してより深い検証を提供し、問題を発見したためです。クライアント側の検証に依存するだけでは十分ではありません。View(model)を返すことはできません。ビュー全体が結果のdivにレンダリングされるので、今、その回避策は何ですか?
CD Smith

54

私はすべての答えが重要なポイントを逃したと思います:

それは(フォームの別のdivの外に及びNOT)自体を更新する必要があるように、あなたはAjaxフォームを使用している場合、あなたは含むのdiv配置する必要がありOUTSIDEフォームのを。例えば:

 <div id="target">
 @using (Ajax.BeginForm("MyAction", "MyController",
            new AjaxOptions
            {
                HttpMethod = "POST",
                InsertionMode = InsertionMode.Replace,
                UpdateTargetId = "target"
            }))
 {
      <!-- whatever -->
 }
 </div>

それ以外の場合は、結果が新しいページに表示される@Davidのように終了します。


7
Davidの問題は、ほとんどの場合、控えめなajaxコードを含むjqueryvalバンドルが含まれていないことが原因です。投稿したこのアプローチには十分注意してください。そうしないと、1つの投稿が表示され、フォームを置き換えただけでフォームがホースされます。次に、フォームを管理し、それにすべてのajaxオプションを再指定するために、「MyAction」ビューが必要です。
Adam Tuliper-MSFT 2013年

私のアプリケーションで、マスターページを含むフォーム全体を表示するdivで私を助けてください
Nitin ...

私にとって、私はUnobtrusiveJavaScriptEnabledどこにもtrueに設定していませんでした
Kunal

15

私は最終的にDarinのソリューションを機能させましたが、最初にいくつかの間違いを犯しました。その結果、Davidと同様の問題が発生しました(Darinのソリューションの下のコメント)。結果は新しいページに投稿されていました。

メソッドが返された後、フォームで何かをしなければならなかったので、後で使用するためにフォームを保存しました。

var form = $(this);

ただし、この変数には、ajax呼び出しで使用される「アクション」または「メソッド」プロパティがありませんでした。

$(document).on("submit", "form", function (event) {
    var form = $(this);

    if (form.valid()) {
        $.ajax({
            url: form.action, // Not available to 'form' variable
            type: form.method,  // Not available to 'form' variable
            data: form.serialize(),
            success: function (html) {
                // Do something with the returned html.
            }
        });
    }

    event.preventDefault();
});

代わりに、「this」変数を使用する必要があります。

$.ajax({
    url: this.action, 
    type: this.method,
    data: $(this).serialize(),
    success: function (html) {
        // Do something with the returned html.
    }
});

5
これは、フォーム変数がjQueryフォームをセレクタとしてオブジェクトに設定しているためです。form[0]プロパティがあります。また、jQuery変数を$簡単に識別できるように変数にプレフィックスを付けることもお勧めします。
James Southが

6

Darin Dimitrovのソリューションは、1つの例外を除いて私にとってうまくいきました。(意図的な)検証エラーのある部分ビューを送信すると、ダイアログに重複したフォームが返されました。

ここに画像の説明を入力してください

これを修正するには、Html.BeginFormをdivでラップする必要がありました。

<div id="myForm">
    @using (Html.BeginForm("CreateDialog", "SupportClass1", FormMethod.Post, new { @class = "form-horizontal" }))
    {
        //form contents
    }
</div>

フォームが送信されたとき、私は成功関数のdivをクリアし、検証されたフォームを出力しました。

    $('form').submit(function () {
        if ($(this).valid()) {
            $.ajax({
                url: this.action,
                type: this.method,
                data: $(this).serialize(),
                success: function (result) {
                    $('#myForm').html('');
                    $('#result').html(result);
                }
            });
        }
        return false;
    });
});

私も同じエラーが出ます。Partial Viewsインデックスページの下に作成関数を表示するために使用しています。部分的なビューですべての検証メッセージを取得できます。しかし、Createが成功すると、インデックスが2回表示されます。Html.BeginFormインデックスビューにはありません。
Vini

UpdateTargetId = "myForm"代わりに使用してみてください
Kunal

4

データ検証が実行されなかった場合、またはコンテンツが常に新しいウィンドウで返される場合は、次の3行がビューの上部にあることを確認してください。

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>

私はそれらを解決策で見つけませんでした。Nugetパッケージマネージャーからインストールする必要がありました
FindOut_Quran

3

//モデル内

public class MyModel
{  
   [Required]
    public string Name{ get; set; }
}

// PartailView //PartailView.cshtml

@model MyModel

<div>
    <div>
      @Html.LabelFor(model=>model.Name)
    </div>
    <div>
        @Html.EditorFor(model=>model.Name)
        @Html.ValidationMessageFor(model => model.Name)
    </div>
</div>

Index.cshtmlビュー

@model MyModel
<div id="targetId">
    @{Html.RenderPartial("PartialView",Model)}
</div>

@using(Ajax.BeginForm("AddName", new AjaxOptions { UpdateTargetId = "targetId", HttpMethod = "Post" }))
{
     <div>
        <input type="submit" value="Add Unit" />
    </div>
}

コントローラ内

public ActionResult Index()
{
  return View(new MyModel());
}


public string AddName(MyModel model)
{
   string HtmlString = RenderPartialViewToString("PartailView",model);
   return HtmlString;
}


protected string RenderPartialViewToString(string viewName, object model)
        {
            if (string.IsNullOrEmpty(viewName))
                viewName = ControllerContext.RouteData.GetRequiredString("action");

            ViewData.Model = model;

            using (StringWriter sw = new StringWriter())
            {
                ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
                ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
                viewResult.View.Render(viewContext, sw);
                return sw.GetStringBuilder().ToString();
            }
        }

ViewNameとModelをRenderPartialViewToStringメソッドに渡す必要があります。モデルに適用され、Index.cshtmlの "targetId" divにコンテンツを追加する検証付きのビューが返されます。このように、部分ビューのRenderHtmlをキャッチすることで、検証を適用できます。


3

Ajaxフォームは、JavaScriptを使用して非同期で動作します。そのため、スクリプトファイルをロードして実行する必要があります。パフォーマンスはわずかに低下しますが、ポストバックなしで実行されます。

HTMLフォームとAjaxフォームの動作の違いを理解する必要があります。

Ajax:

  1. RedirectAction()を実行しても、フォームをリダイレクトしません。

  2. 保存、更新、および変更操作を非同期で実行します。

HTML:

  1. フォームをリダイレクトします。

  2. 同期と非同期の両方で操作を実行します(追加のコードと注意が必要)。

以下のリンクでPOCとの違いを示しました。 リンク


1

Ajax.BeginFormを追加する前。以下のスクリプトを、記載されている順序でプロジェクトに追加します。

  1. jquery-1.7.1.min.js
  2. jquery.unobtrusive-ajax.min.js

これら2つだけでAjax操作を実行できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.