内容有多大?请注意,您可能会看到很多时间,因为您正在同步而不是异步调用此网络调用。
您可以提前异步读取字符串并将其存储在请求属性中。
或者,您可以编写一个格式化程序,然后用 [FromBody] 装饰您的参数。
这里推荐的方法是使用 FromBody 和格式化程序,因为它自然适合 WebAPI 架构:
为此,您将编写一个媒体类型格式化程序:
public class StringFormatter : MediaTypeFormatter
{
public StringFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/mystring"));
}
public override bool CanReadType(Type type)
{
return (type == typeof (string));
}
public override bool CanWriteType(Type type)
{
return false;
}
public override async Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger,
CancellationToken cancellationToken)
{
if (!CanReadType(type))
{
throw new InvalidOperationException();
}
return await content.ReadAsStringAsync();
}
}
注册它webapiconfig.cs
config.Formatters.Add(new StringFormatter());
并在一个动作中消费
public string Get([FromBody]string myString)
{
return myString;
}
另一种设计(不推荐,因为过滤器和粘合剂之间的耦合):
实现一个模型绑定器(这太天真了):
public class MyStringModelBinder : IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
// this is a Naive comparison of media type
if (actionContext.Request.Content.Headers.ContentType.MediaType == "application/mystring")
{
bindingContext.Model = actionContext.Request.Properties["MyString"] as string;
return true;
}
return false;
}
}
添加一个授权过滤器(它们在模型绑定之前运行),您可以异步访问该操作。这也适用于委托处理程序:
public class MyStringFilter : AuthorizationFilterAttribute
{
public override async Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
if (actionContext.Request.Content.Headers.ContentType.MediaType == "application/mystring")
{
var myString = await actionContext.Request.Content.ReadAsStringAsync();
actionContext.Request.Properties.Add("MyString", myString);
}
}
}
在 WebApi.Config 中注册或应用到控制器:
WebApiConfig.cs
config.Filters.Add(new MyStringFilter());
值控制器.cs
[MyStringFilter] // this is optional, you can register it globally as well
public class ValuesController : ApiController
{
// specifying the type here is optional, but I'm using it because it avoids having to specify the prefix
public string Get([ModelBinder(typeof(MyStringModelBinder))]string myString = null)
{
return myString;
}
}
(感谢@Kiran Challa 看着我的肩膀,并建议使用授权过滤器)
编辑:对于相对较大的字符串(消耗超过 85KB,因此大约 40K 字符)要始终记住的一件事可能会进入大对象堆,这将对您的站点性能造成严重破坏。如果您认为这很常见,请将输入分解为字符串构建器/字符串数组或类似的东西,而无需连续内存。请参阅为什么使用大对象堆以及我们为什么要关心?