我正在使用Visual Studio 2012目标.Net 4+开发(自托管)WebApi应用程序,并着眼于尽快迁移到VS2013以利用MVC 5和WebApi 2.0。
我需要在所有传出的Uri前面添加一个字符串,该字符串作为传入请求的查询参数发送。挑战是在控制器,模型或视图/视图模型中没有任何特定代码的情况下执行此操作。如果可能的话,我还想避免使用需要使用反射/递归来处理传出响应的所有属性的动作过滤器,尽管使用结果动作过滤器来制作url前缀可用于序列化程序。
我到目前为止所提供的是DelegatingHandler
来获取请求的查询参数中使用的url前缀,因此可以将其作为属性添加到某个请求/控制器上下文对象中;并使用JsonConverter
为响应中的所有Uri
类型属性添加所需的前缀。
我剩下的就是将请求参数中指定的Url前缀转换为转换器。传递给JsonConvertor
的序列化程序确实具有Context
属性,但我无法看到它是否以及如何与请求上下文相关。
我可以想出一些方法来解决这个问题,但是对于MVC / WebApi如何在管道周围传递请求(上下文)信息,仍然会遇到“缺乏知识”的障碍。
委派处理程序:
class UrlPrefixHandler : DelegatingHandler
{
private string GetUrlPrefixValue(HttpRequestMessage request)
{
var queryStrings = request.GetQueryNameValuePairs();
if (queryStrings == null)
return null;
var match = queryStrings.FirstOrDefault(kv => string.Compare(kv.Key, "url_prefix", true) == 0);
if (string.IsNullOrEmpty(match.Value))
return null;
return match.Value;
}
async protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
string urlPrefix = GetUrlPrefixValue(request);
// TODO : How do I get this to the serializer on a per request basis?
// and do this without placing requirements on controllers/models/views?
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
return response;
}
}
Json转换器:
class UriPrefixConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(Uri).IsAssignableFrom(objectType);
}
public override bool CanRead
{
get { return false; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter.");
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JObject result = new JObject();
//serializer.
Uri u = (Uri)value as Uri;
// TODO : Getting the prefix from the request's context somehow
Uri prefixed = new Uri("/uriPrefix" + u.OriginalString, UriKind.Relative);
writer.WriteValue(prefixed.OriginalString);
}