MVC Beta UpdateModel 多載接受 IValueProvider,允許自訂表單值到複雜型別(如 StateList<T>)的轉換邏輯,解決預設繫結器無法處理集合屬性的問題。
部落格文章包含 Tags: StateList<string>、Categories: StateList<Category>,表單提交逗號分隔字串,需轉換為強型別集合。
public interface IValueProvider
{
ValueProviderResult GetValue(string key);
}
public class PostValueProvider : IValueProvider
{
private readonly ControllerContext _context;
public PostValueProvider(ControllerContext context)
{
_context = context;
}
public ValueProviderResult GetValue(string name)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentException("參數不可為空", nameof(name));
switch (name)
{
case "Tags":
return GetTagsValue();
case "Categories":
return GetCategoriesValue();
default:
return new DefaultValueProvider(_context).GetValue(name); // 回退預設
}
}
private ValueProviderResult GetTagsValue()
{
string raw = GetRawValue("Tags");
if (string.IsNullOrEmpty(raw)) return null;
var tags = raw.Split(',', StringSplitOptions.RemoveEmptyEntries)
.Select(t => t.Trim().ToLowerInvariant());
var list = new StateList();
foreach (var tag in tags) list.Add(tag);
return new ValueProviderResult(list, raw, CultureInfo.InvariantCulture);
}
private ValueProviderResult GetCategoriesValue()
{
string raw = GetRawValue("Categories");
if (string.IsNullOrEmpty(raw)) return null;
var ids = raw.Split(',', StringSplitOptions.RemoveEmptyEntries);
var list = new StateList();
foreach (var id in ids)
list.Add(Category.GetCategory(new Guid(id)));
return new ValueProviderResult(list, raw, CultureInfo.InvariantCulture);
}
private string GetRawValue(string key)
{
var req = _context.HttpContext.Request;
return req.Form[key] ?? req.QueryString[key];
}
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult SaveNewPost()
{
var post = new Post();
var provider = new PostValueProvider(ControllerContext);
try
{
UpdateModel(post, new[] { "Title", "Content", "Slug", "Tags", "Categories" }, provider);
}
catch
{
return View(post);
}
repository.Save(post);
return RedirectToAction("Index");
}
DefaultValueProvider,保持標準行為原始值(供錯誤訊息顯示)、轉換後物件、CultureInfo