Last active
December 16, 2015 17:20
-
-
Save KatsuYuzu/2a20697338eeabb93376 to your computer and use it in GitHub Desktop.
ASP.NET MVC カスタムモデルバインダー
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Web.Mvc; | |
using System.Web.Optimization; | |
using System.Web.Routing; | |
using WebApplication.Common; | |
namespace WebApplication | |
{ | |
public class MvcApplication : System.Web.HttpApplication | |
{ | |
protected void Application_Start() | |
{ | |
AreaRegistration.RegisterAllAreas(); | |
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); | |
RouteConfig.RegisterRoutes(RouteTable.Routes); | |
BundleConfig.RegisterBundles(BundleTable.Bundles); | |
// モデルバインダーの登録 | |
// グローバルで一括登録するならキー型は nullable も忘れずに! | |
// カスタムバインダー側は nullable でなくておk。 | |
// コントローラーやアクションでの個別利用なら適宜どうぞ。 | |
ModelBinders.Binders.Add(typeof(int), new ThousandsSeparatorNumberBinder<int>()); | |
ModelBinders.Binders.Add(typeof(int?), new ThousandsSeparatorNumberBinder<int>()); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Web.Mvc; | |
using WebApplication.Models; | |
namespace WebApplication.Controllers | |
{ | |
public class HomeController : Controller | |
{ | |
public ActionResult Index(Test model) | |
{ | |
ViewBag.message = string.Format("値: {0}", model.Number); | |
return View(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@model WebApplication4.Models.Test | |
<form> | |
<h2>数値を入力してください。</h2> | |
@Html.TextBoxFor(x => x.Number) | |
<input type="submit" value="送信" /> | |
<h2>結果</h2> | |
<strong>@ViewBag.message</strong> | |
@Html.ValidationSummary() | |
</form> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.ComponentModel.DataAnnotations; | |
namespace WebApplication.Models | |
{ | |
public class Test | |
{ | |
[Display(Name = "数値")] | |
public int? Number { get; set; } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Globalization; | |
using System.Web.Mvc; | |
namespace WebApplication.Common | |
{ | |
/// <summary> | |
/// 1000 の桁で区切られた数字のブラウザー要求を数値型に対応付けます。 | |
/// </summary> | |
/// <typeparam name="T">対応付ける数値型。</typeparam> | |
public class ThousandsSeparatorNumberBinder<T> | |
: DefaultModelBinder | |
where T : struct, IConvertible | |
{ | |
/// <summary> | |
/// 送信された文字列の変換に使うパーサー。 | |
/// </summary> | |
private static readonly Func<string, object> Parser; | |
/// <summary> | |
/// パーサーを初期化します。 | |
/// </summary> | |
static ThousandsSeparatorNumberBinder() | |
{ | |
// short, long は int と同様、float, double は decimal と同様なので割愛 | |
var parsers = new Dictionary<Type, Func<string, object>> | |
{ | |
{ | |
typeof(int), | |
(string value) => int.Parse(value, NumberStyles.Integer | NumberStyles.AllowThousands) | |
}, | |
{ | |
typeof(decimal), | |
(string value) => decimal.Parse(value, NumberStyles.Number) | |
} | |
}; | |
Parser = parsers[typeof(T)]; | |
} | |
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) | |
{ | |
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); | |
if (valueProviderResult == null) | |
{ | |
return base.BindModel(controllerContext, bindingContext); | |
} | |
// モデルステートの設定 | |
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult); | |
// 値の文字列 | |
var valueString = valueProviderResult.AttemptedValue; | |
// 以下、変換処理 | |
if (string.IsNullOrWhiteSpace(valueString)) | |
{ | |
return null; | |
} | |
try | |
{ | |
return Parser(valueString); | |
} | |
catch (Exception ex) | |
{ | |
bindingContext.ModelState.AddModelError(bindingContext.ModelName, ex); | |
return null; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment