在剛發布的ASP.NET MVC Beta版中,在UpdataModel方法中提供了一個帶有IValueProvider參數的重載。那麼這個IValueProvider有什麼用呢?
我們先來看一個簡單的場景,例如我們的blog系統有一個Post的對象,Post對象有一個Tags屬性和Categories屬性,他們的類型分別是:
Post.Tags : StateList<string> (BlogEngine.NET 中的一個List<T>的擴展類型)
Post.Categories : StateList<Category>
假如我們要使用UpdataModel方法來對我們Post過來的Form表單數據更新到我們的Post對象中,可能會有如下的代碼:
/// <summary>
很明顯,在上面的代碼中,我們用UpdateModel來更新Tags和Categories屬性的時候,是不可能成功的,因為UpdateModel方法不知道怎樣將Form提交過來的"Tags"和"Categories"數據轉換為StateList<string>類型和StateList<Category>類型。這時候就需要我們提供一個ValueProvider,來進行這個轉換。
/// 將提交過來的新隨筆表單內容保存到數據庫
/// </summary>
[AcceptVerbs("POST"), ActionName("NewPost")]
public ActionResult SaveNewPost(FormCollection form)
{
Post post = new Post();
try
{
UpdateModel(post, new[] { "Title", "Content", "Slug", "Tags", "Categories" });
}
catch
{
return View(post);
}
..
}
要實現一個ValueProvider,我們只需要實現IValueProvider接口的GetValue方法,並且返回一個ValueProviderResult的結果就可以了。下面我們就寫一個PostValueProvider來實現上面我們提出的情況。代碼如下:
PostValueProvider
public class PostValueProvider : IValueProvider
{
private ControllerContext context;
//private DefaultValueProvider dProvider;
public PostValueProvider(ControllerContext context)
{
this.context = context;
//dProvider = new DefaultValueProvider(context);
}
#region IValueProvider 成員
public ValueProviderResult GetValue(string name)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentException("參數不能為空", "name");
}
switch (name)
{
case "Tags":
return GetTagsValue();
case "Categories":
return GetCategoriesValue();
default:
return new DefaultValueProvider(context).GetValue(name);
}
}
#endregion
private ValueProviderResult GetTagsValue()
{
string strTags = GetValueFromRequest("Tags");
if (string.IsNullOrEmpty(strTags))
{
return null;
}
string[] tags = strTags.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
StateList<string> tagsList = new StateList<string>();
foreach (string tag in tags)
{
tagsList.Add(tag.Trim().ToLowerInvariant());
}
return new ValueProviderResult(tagsList, strTags, CultureInfo.InvariantCulture);
}
private ValueProviderResult GetCategoriesValue()
{
string strCategories = GetValueFromRequest("Categories");
if (string.IsNullOrEmpty(strCategories))
{
return null;
}
string[] categories = strCategories.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
StateList<Category> list = new StateList<Category>();
foreach (string c in categories)
{
list.Add(Category.GetCategory(new Guid(c)));
}
return new ValueProviderResult(list, strCategories, CultureInfo.InvariantCulture);
}
private string GetValueFromRequest(string name)
{
string value = null;
HttpRequestBase request = context.HttpContext.Request;
if (request != null)
{
if (request.QueryString != null)
{
value = request.QueryString[name];
}
if (string.IsNullOrEmpty(value) && (request.Form != null))
{
value = request.Form[name];
}
}
return value;
}
}