WebApi 通过ModelBinder绑定自定义参数对象
绑定action内参数对象的方法有很多种,无论是针对简单对象,还是复杂对象。比如 typeConverter 有兴趣的,可以看看我其他文章
但是如果需要在绑定参数的过程中进行某些验证,或者绑定对象的数据并不单单来源于用户传过来的值,比如获取请求的所有Cookie对象等等
这种情况的话,比 typeConverter 更好的方法就是自定义ModelBinder,那么实际WebApi绑定参数的流程是怎么样的呢。
通过 ValueProviderFactory 获得 ValueProvider
调用ValueProvider类里面ContainsPrefix方法,判定 ValueProvider 是否包含参数 的名称key
如果包含,那么
通过在类上定义的ModelBinder类,调用ModelBinder类的BindModel方法
在BindModel方法内 通过 bindingContext.ValueProvider获取
定义在action内描述参数特性的ValueProvider,比如[ValueProvider(typeof(DictionaryValueProviderFactory))]
ValueProviderResult result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
通过bindingContext.ModelName 获取参数名称,继而调用ValueProvider.GetValue,获取ValueProvider内key对应的对象,并封装成ValueProviderResult 返回
将 ValueProviderResult.rawValue 赋给Model,那么参数就会被绑定model的值
bindingContext.Model = ValueProviderResult.rawValue
先上前台页面

Client端代码
private void button2_Click(object sender, EventArgs e) { HttpWebRequest request=(HttpWebRequest) WebRequest.Create("http://localhost:29828/api/Demo"); request.Method = "GET"; Cookie c = new Cookie("name", "zhangsan", "/api", "localhost"); c.Expires = DateTime.Now.AddDays(1); Cookie c2 = new Cookie("psd", "123456", "/", "localhost"); c2.Expires = DateTime.Now.AddDays(1); CookieContainer cookies = new CookieContainer(); request.CookieContainer = cookies; request.CookieContainer.Add(c); request.CookieContainer.Add(c2); //通过URL传值的话,可以不指定 contentType //request.ContentType = "text/html;charset=utf-8"; //request.ContentType = "application/x-www-form-urlencoded;charset=utf-8"; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { using (StreamReader reader = new StreamReader(response.GetResponseStream())) { string result = reader.ReadToEnd(); this.textBox1.Text = result; } foreach (Cookie item in response.Cookies) // 获取 服务器传回的Cookie { this.textBox1.Text += item.Name; this.textBox1.Text += item.Value; } } }
看Server端代码结构

using System.Web.Http;
using System.Web.Http.ValueProviders;
using WebApi.Models;
namespace WebApi.Controllers
{
public class DemoController : ApiController
{
public LoginCookieUser Get2([ValueProvider(typeof(CookieValueProviderFactory))] LoginCookieUser name)
{
return name;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.ModelBinding;
using System.Runtime.Serialization;
namespace WebApi.Models
{
[ModelBinder(typeof(CookieValueModelBinder))]
[DataContract]
public class LoginCookieUser
{
[DataMember]
public string loginuser { get; set; }
[DataMember]
public string Domain { get; set; }
[DataMember]
public DateTime Expires { get; set; }
[DataMember]
public string Path { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.ModelBinding;
using System.Web.Http.ValueProviders;
using WebApi.Models;
namespace WebApi
{
public class CookieValueModelBinder : IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
ValueProviderResult result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (result == null)
{
return false;
}
object rawValue = result.RawValue;
LoginCookieUser user = new LoginCookieUser();
user.loginuser = result.RawValue.ToString();
if (bindingContext.ModelType.IsInstanceOfType(user))
{
//如果ModelMetadata的ConvertEmptyStringToNull属性为True
//并且原始类型是一个空白字符串
//将绑定的Model对象设置为Null
if (rawValue is string && string.IsNullOrWhiteSpace((string)rawValue) && bindingContext.ModelMetadata.ConvertEmptyStringToNull)
{
rawValue = null;
}
bindingContext.Model = user;
//向客户端传送Cookie
var cookie = new HttpCookie("servercookie", "fromServer");
cookie.Expires = DateTime.Now.AddHours(1);
HttpContext.Current.Response.AppendCookie(cookie);
return true;
}
return false;
}
}
}
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.ValueProviders;
namespace WebApi
{
public class CookieValueProvider : IValueProvider
{
private Dictionary<string, string> _values;
public CookieValueProvider(HttpActionContext actionContext)
{
if (actionContext == null)
{
throw new ArgumentNullException("actionContext");
}
_values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (CookieHeaderValue cookie in actionContext.Request.Headers.GetCookies())
{
foreach (CookieState state in cookie.Cookies)
{
_values[state.Name] = state.Value;
}
}
}
public bool ContainsPrefix(string prefix)
{
return _values.Keys.Contains(prefix);
}
public ValueProviderResult GetValue(string key)
{
string value;
if (_values.TryGetValue(key, out value))
{
return new ValueProviderResult(value, value, CultureInfo.InvariantCulture);
}
return null;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.ValueProviders;
namespace WebApi
{
public class CookieValueProviderFactory : ValueProviderFactory
{
public override IValueProvider GetValueProvider(HttpActionContext actionContext)
{
return new CookieValueProvider(actionContext);
}
}
}

浙公网安备 33010602011771号