首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> 關於ASP.NET

ASP.NET MVC Beta IValueProvider 介面實作:自訂表單值轉換支援複雜型別

     編輯:關於ASP.NET

MVC Beta UpdateModel 多載接受 IValueProvider,允許自訂表單值到複雜型別(如 StateList<T>)的轉換邏輯,解決預設繫結器無法處理集合屬性的問題。

應用場景

部落格文章包含 Tags: StateList<string>、Categories: StateList<Category>,表單提交逗號分隔字串,需轉換為強型別集合。

IValueProvider 介面定義

public interface IValueProvider
{
    ValueProviderResult GetValue(string key);
}

完整實作:PostValueProvider

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,保持標準行為
  • ValueProviderResult:攜帶 原始值(供錯誤訊息顯示)、轉換後物件、CultureInfo
  • 單一職責:只負責值轉換,不含驗證邏輯(由 ModelState 處理)
  • 可測試性:ControllerContext 可 Mock,單元測試極簡單
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved