Asp.net web api ModelBinder Request.Content.ReadAsStringAsync性能

Asp.net web api ModelBinder Request.Content.ReadAsStringAsync性能,asp.net-web-api,performance-testing,ants,Asp.net Web Api,Performance Testing,Ants,我有一个定制的ModelBinder,当我加载测试我的应用程序并在其上运行Ants profiler时,它识别读取请求。内容作为字符串作为热点: public class QueryModelBinder : IModelBinder { public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) { var

我有一个定制的ModelBinder,当我加载测试我的应用程序并在其上运行Ants profiler时,它识别读取请求。内容作为字符串作为热点:

 public class QueryModelBinder : IModelBinder
    {
        public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
        {
            var body = actionContext.Request.Content.ReadAsStringAsync().Result;
有没有更有效的方法? 还是我读错了蚂蚁档案


内容有多大?请注意,您可能会看到很多时间,因为您正在同步而不是异步调用此网络调用

您可以通过异步读取字符串,并将其存储在请求属性中

或者,您可以编写格式化程序,然后用[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();
    }
}
并在行动中消费

public string Get([FromBody]string myString)
{
    return myString;
}
另一种设计(由于过滤器和粘合剂之间的耦合,因此不推荐):

实现一个模型绑定器(这非常简单):

添加一个身份验证过滤器(它们在modelbinding之前运行),您可以异步访问该操作。这也适用于委托处理程序:

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

ValuesController.cs

(感谢@Kiran Challa回头看我,并建议使用授权过滤器)


编辑:对于相对较大的字符串(消耗超过85KB,因此大约40K个字符),有一件事要记住,它可能会进入大型对象堆,这将对站点性能造成严重破坏。如果您认为这很常见,请将输入分解为字符串生成器/字符串数组或类似的没有连续内存的内容。请参见内容有多大?请注意,您可能会看到很多时间,因为您正在同步而不是异步调用此网络调用

您可以通过异步读取字符串,并将其存储在请求属性中

或者,您可以编写格式化程序,然后用[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();
    }
}
并在行动中消费

public string Get([FromBody]string myString)
{
    return myString;
}
另一种设计(由于过滤器和粘合剂之间的耦合,因此不推荐):

实现一个模型绑定器(这非常简单):

添加一个身份验证过滤器(它们在modelbinding之前运行),您可以异步访问该操作。这也适用于委托处理程序:

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

ValuesController.cs

(感谢@Kiran Challa回头看我,并建议使用授权过滤器)


编辑:对于相对较大的字符串(消耗超过85KB,因此大约40K个字符),有一件事要记住,它可能会进入大型对象堆,这将对站点性能造成严重破坏。如果您认为这很常见,请将输入分解为字符串生成器/字符串数组或类似的没有连续内存的内容。例如,请参见过滤器中的

,因为该过滤器是异步的。我不确定我是否在遵循,请包含示例?添加了两个示例。请注意,您需要一个授权筛选器而不是操作筛选器,因为操作筛选器在模型绑定之后运行。例如,在筛选器中,由于筛选器是异步的。我不确定我是否遵循此要求,请包含示例?添加了两个示例。请注意,您需要授权筛选器而不是操作筛选器,因为操作筛选器在模型绑定之后运行。
[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;
    }
}