ASP.NET MVC 4(8)URLリンクとAjaxヘルプ関数

41012 ワード

ヘルプ関数を使用したリンクの作成
MVCは、パスマッピングテーブルに基づいて生成されたURLを自動的に調整するヘルプ関数作成リンクを提供する.
説明

出力結果
アプリケーション相対URL
Url.Content("~/Content/Site.css")
 /Content/Site.css
コントローラアクションへのリンク
Html.ActionLink("My Link", "Index", "Home")
My Link 
ActionのURL
Url.Action("GetPeople", "People")
/People/GetPeople 
パスマップを使用したURL
Url.RouteUrl(new {controller = "People", action="GetPeople"}) 
/People/GetPeople 
パスマッピングを使用したリンク
Html.RouteLink("My Link", new {controller = "People", action="GetPeople"})
My Link
名前付きパスマッピングのリンク
Html.RouteLink("My Link", "FormRoute", new {controller = "People", action="GetPeople"})
My Link 
MVC Unobtrusive Ajaxの使用
MVC内蔵jQueryベースのunobtrusive Ajaxのサポートは、unobtrusive Ajaxと呼ばれるのは、従来のAjaxのようにXMLが多く使われていないためです.unobtrusive Ajaxを使用するには、まずweb.configのconfiguration/appSettingsのセクションでは、U nobtrusiveJavaScriptEnabledのサポートを開始します.
... 
<configuration> 
<!-- other elements omitted for brevity --> 
<appSettings> 
<add key="webpages:Version" value="2.0.0.0" /> 
<add key="webpages:Enabled" value="false" /> 
<add key="PreserveLoginUrl" value="true" /> 
<add key="ClientValidationEnabled" value="true" /> 
<add key="UnobtrusiveJavaScriptEnabled" value="true" /> 
</appSettings> 
<!-- other elements omitted for brevity --> 
</configuration> 
... 

関連するjavascriptファイルを参照する必要があります.これらのスクリプトファイルへの参照をレイアウトファイルに配置できます.layout.cshtml:
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link href="~/Content/Site.css" rel="stylesheet"/>
    <script src="~/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
    <script src="~/Scripts/jquery.unobtrusive-ajax.min.js" type="text/javascript"></script>
</head>
<body>
    @RenderBody()
</body>
</html>

jquery-1.7.1.min.jsはjQueryのコアライブラリ、jquery.unobtrusive-ajax.min.jsは、ファイル名のAjax機能(jqueryライブラリベース)を提供する.minはデバッグがほとんど不可能な縮小バージョンを示し、開発時に非を使用することができる.minバージョンは、リリース時に再採用する.minバージョン.
Unobtrusive Ajaxフォームの使用
次に、コントローラからAjaxフォームを使用する方法を例に示します.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using HelperMethods.Models;
namespace HelperMethods.Controllers
{
    public class PeopleController : Controller
    {
        private Person[] personData = { 
new Person {FirstName = "Adam", LastName = "Freeman", Role = Role.Admin}, 
new Person {FirstName = "Steven", LastName = "Sanderson", Role = Role.Admin}, 
new Person {FirstName = "Jacqui", LastName = "Griffyth", Role = Role.User}, 
new Person {FirstName = "John", LastName = "Smith", Role = Role.User}, 
new Person {FirstName = "Anne", LastName = "Jones", Role = Role.Guest} 
};
        public ActionResult Index()
        {
            return View();
        }
        public PartialViewResult GetPeopleData(string selectedRole = "All")
        {
            IEnumerable<Person> data = personData;
            if (selectedRole != "All")
            {
                Role selected = (Role)Enum.Parse(typeof(Role), selectedRole);
                data = personData.Where(p => p.Role == selected);
            }
            return PartialView(data);
        }
        public ActionResult GetPeople(string selectedRole = "All")
        {
            return View((object)selectedRole);
        }
    }
}

GetPeopleData()メソッドは、選択されたロールに基づいてPersonリストをフィルタリングし、対応するGetPeopleDataをセグメントビューに返す.cshtml:
@using HelperMethods.Models
@model IEnumerable<Person>

@foreach (Person p in Model) {
    <tr>
        <td>@p.FirstName</td>
        <td>@p.LastName</td>
        <td>@p.Role</td>
    </tr>                
}

GetpeopleData()を呼び出し、Ajax formを作成します.
@using HelperMethods.Models
@model string
@{
    ViewBag.Title = "GetPeople";
    AjaxOptions ajaxOpts = new AjaxOptions
    {
        UpdateTargetId = "tableBody"
    };
}
<h2>Get People</h2>
<table>
    <thead><tr><th>First</th><th>Last</th><th>Role</th></tr></thead>
    <tbody id="tableBody">
        @Html.Action("GetPeopleData", new { selectedRole = Model })
    </tbody>
</table>
@using (Ajax.BeginForm("GetPeopleData", ajaxOpts))
{
    <div>
        @Html.DropDownList("selectedRole", new SelectList(new[] { "All" }.Concat(Enum.GetNames(typeof(Role)))))
        <button type="submit">Submit</button>
    </div>
} 

Ajax.BeginForm()パラメータとしてAjaxOptionsオブジェクトを使用して作成されたHTML結果:
... 
<form action="/People/GetPeopleData" data-ajax="true" data-ajax-mode="replace" data-ajax-update="#tableBody"id="form0" method="post"> 
... 

ブラウザがGetPeopleページを要求するときjquery.unobtrusive-ajax.jsはdata-ajax=trueのユニットをスキャンし、ajaxのフォームであることを確認し、コミットをクリックするとページ全体をリフレッシュせず、/people/getpeopledataから戻った結果でtablebodyの内容を置き換える.
Ajax options
AjaxOptionsは、サーバに非同期で要求する方法を制御します.これらの属性が含まれています.
ツールバーの
説明
Confirm
非同期リクエストの開始時にユーザーにメッセージを表示し、確認します.
HttpMethod
リクエストのHTTPメソッドを設定するには、getまたはpostでなければなりません
InsertionMode
サーバ結果が返すHTMLを埋め込む方法は、InsertAfter、InsertBefore、Replace(デフォルト)です.
LoadingElementId
Ajax要求時に表示するLoadingユニット要素IDの指定
LoadingElementDuration
Loading要素のアニメーション表示の時間
UpdateTargetId
要求返却結果挿入する要素ID
Url
Ajaxフォーム提出のURL
上のGetPeopleビューAjax formでコミットされたURLは/people/GetPeopleDataです.Javaスクリプトがユーザーによって禁止されている場合、formをコミットして返される結果はGetPeopleDataセクションビューにすぎません.ajaxOptionsでajax要求のURLを直接指定して解決できます.
@using HelperMethods.Models
@model string
@{
    ViewBag.Title = "GetPeople";
    AjaxOptions ajaxOpts = new AjaxOptions
    {
        UpdateTargetId = "tableBody",
        Url = Url.Action("GetPeopleData"),
        LoadingElementId = "loading",
        LoadingElementDuration = 1000,
        Confirm = "Do you wish to request new data?"
    };
}
<h2>Get People</h2>
<div id="loading" class="load" style="display:none">
    <p>Loading Data...</p>
</div>
<table>
    <thead><tr><th>First</th><th>Last</th><th>Role</th></tr></thead>
    <tbody id="tableBody">
        @Html.Action("GetPeopleData", new { selectedRole = Model })
    </tbody>
</table>
@using (Ajax.BeginForm(ajaxOpts))
{
    <div>
        @Html.DropDownList("selectedRole", new SelectList(
new[] { "All" }.Concat(Enum.GetNames(typeof(Role)))))
        <button type="submit">Submit</button>
    </div>
}

生成されたフォームHTML:
... 
<form action="/People/GetPeople"data-ajax="true" data-ajax-mode="replace" data-ajax-update="#tableBody" data-ajax-url="/People/GetPeopleData"id="form0" method="post"> 
... 

このようにフォームにコミットされたURLは依然として/people/GetPeopleであり、javaスクリプトが戻ってくるのを禁止してもGetPeopleページであり、ajax要求されたURLはdata-ajax-urlによって/people/GetPeopleDataとして指定される.AjaxOptionsも設定します.LoadingElementIdはLoadingであり、これはdiplay:noneスタイルのDIV要素であり、AJAX非同期要求時に1秒のみ表示される(LoadingElementDuration=1000).AjaxOptions.Confirm= "Do you wish to request new data?",Ajaxリクエストのたびに、WebページのMessageダイアログ・ボックスがポップアップされます(ダイアログ・メッセージは、ここで設定した「Do you wish to request new data?」です).
Ajaxリンク
上記の例では、ajax非同期リクエストにリンクを使用する場合、フォームを使用してデータをコミットします.
...
<div> 
@foreach (string role in Enum.GetNames(typeof(Role))) { 
  <div class="ajaxLink"> 
  @Ajax.ActionLink(role, "GetPeopleData", 
    new {selectedRole = role}, 
    new AjaxOptions {UpdateTargetId = "tableBody"}) 
  </div> 
} 
</div> 
...

ここでrole列挙の各要素に対してリンクを生成し、生成されたリンク要素は類似しています.
... 
<a data-ajax="true" data-ajax-mode="replace" data-ajax-update="#tableBody" href="/People/GetPeopleData?selectedRole=Guest">Guest</a> 
... 

リンクをクリックするとajaxから返されるHTMLデータがtableBody要素に置き換えられ、フォームを使用してajaxリクエストを送信するのと同じ効果が得られます.同様にjavaスクリプトを無効にすると、getpeopledataセクションビューだけが返されます.このように改善できます.
<div> 
@foreach (string role in Enum.GetNames(typeof(Role))) { 
  <div class="ajaxLink"> 
  @Ajax.ActionLink(role, "GetPeople", 
    new {selectedRole = role}, 
    new AjaxOptions { UpdateTargetId = "tableBody", Url = Url.Action("GetPeopleData", new {selectedRole = role}) 
    }) 
  </div> 
} 
</div> 

リンクリクエストのアドレスはGetPeople,AjaxリクエストのURLはGetPeopleDataのみであり,リクエストのHTML結果はtablebodyに作用する.
Ajaxコールバック
AjaxOptionsクラスのプロパティのセットを暴露すると、ajaxリクエストサイクルでこれらのスクリプト関数を呼び出すjavaスクリプト関数を指定できます.
ツールバーの
jQueryイベント
説明
OnBegin
beforeSend
Ajaxリクエスト送信前に呼び出す
OnComplete
complete
要求が成功したときに呼び出す
OnFailure
error
要求が失敗したときに呼び出す
OnSuccess
success
リクエストが成功したかどうかにかかわらず、リクエストが完了したときに呼び出されます.
コールバック関数と組み合わせて、上記の例をさらに変更することができます.まず、コントローラのGetPeopleDataメソッドを変更します.
        public ActionResult GetPeopleData(string selectedRole = "All")
        {
            IEnumerable<Person> data = personData;
            if (selectedRole != "All")
            {
                Role selected = (Role)Enum.Parse(typeof(Role), selectedRole);
                data = personData.Where(p => p.Role == selected);
            }
            if (Request.IsAjaxRequest())
            {
                var formattedData = data.Select(p => new
                {
                    FirstName = p.FirstName,
                    LastName = p.LastName,
                    Role = Enum.GetName(typeof(Role), p.Role)
                });
                return Json(formattedData, JsonRequestBehavior.AllowGet);
            }
            else
            {
                return PartialView(data);
            }
        } 

私たちはRequestを使います.IsajaxRequestは、要求がajaxから来たかどうかを判断します.これは、ブラウザがajax要求時にヘッダにX-Requested-With=XMLhttpRequestを含むことに基づいています.要求がajaxから来た場合、コントローラメソッドはJson(data,JsonRequestBehavior.AllowGet)が作成したJsonResultオブジェクトを返す、デフォルトJSONデータはPOST要求でのみ送信、ここでは2番目のパラメータでJsonRequestBehaviorを指定する.AllowGetはGETリクエストでJSONデータを使用することを許可する.MVCフレームワークはformattedDataのjsonパッケージを担当し、パッケージのフォーマットはMVCが最適な方法で決定しようと試みたが、ここで返されたJSONデータは類似している.
... 
{"PersonId":0,"FirstName":"Adam","LastName":"Freeman", 
"BirthDate":"\/Date(62135596800000)\/","HomeAddress":null,"IsApproved":false,"Role":0} 
... 

ビューでは、AjaxOptionsのOnSucessコールバック関数で、返されたJSONデータを処理します.
@using HelperMethods.Models
@model string
@{ 
    ViewBag.Title = "GetPeople";
    AjaxOptions ajaxOpts = new AjaxOptions
    {
        //UpdateTargetId = "tableBody",
        Url = Url.Action("GetPeopleData"),
        LoadingElementId = "loading",
        LoadingElementDuration = 1000,
        OnSuccess = "processData" 
    };
}
<script type="text/javascript">
    function processData(data) {
        var target = $("#tableBody");
        target.empty();
        for (var i = 0; i < data.length; i++) {
            var person = data[i];
            target.append("<tr><td>" + person.FirstName + "</td><td>"
            + person.LastName + "</td><td>" + person.Role + "</td></tr>");
        }
    }
</script>
<h2>Get People</h2>
<div id="loading" class="load" style="display: none">
    <p>Loading Data...</p>
</div>
<table>
    <thead>
        <tr>
            <th>First</th>
            <th>Last</th>
            <th>Role</th>
        </tr>
    </thead>
    <tbody id="tableBody">
        @Html.Action("GetPeopleData", new { selectedRole = Model })
    </tbody>
</table>
@using (Ajax.BeginForm(ajaxOpts))
{ 
    <div>
        @Html.DropDownList("selectedRole", new SelectList(
new[] { "All" }.Concat(Enum.GetNames(typeof(Role)))))
        <button type="submit">Submit</button>
    </div> 
}

<div>
    @foreach (string role in Enum.GetNames(typeof(Role)))
    { 
        <div class="ajaxLink">
            @Ajax.ActionLink(role, "GetPeople",
new { selectedRole = role },
new AjaxOptions
{
    Url = Url.Action("GetPeopleData", new { selectedRole = role }),
    OnSuccess = "processData"
})
        </div> 
    }
</div>

スクリプト関数processDataはAjaxOptionsのOnSuccessコールバック時に呼び出され、要求されたJSONデータを処理し、そこからPersonオブジェクトを分割し、これらのデータに基づいてtableBodyラベルの内容を直接書き換えるので、AjaxOptionsでUpdateTargetIdを通じてコンテンツを置き換える要素を指定する必要はありません.
 
以上は『Apress Pro ASP.NET MVC 4』第4版の関連内容のまとめであり、不詳な点は原版http://www.apress.com/9781430242369を参照.