ModelBinder的Request.Content.ReadAsStringAsync性能(Mo

2019-10-20 02:42发布

我有一个自定义的模型绑定器,其中,当我加载测试我的应用程序,并运行蚂蚁上探查,识别读取Request.Content作为字符串作为热点:

 public class QueryModelBinder : IModelBinder
    {
        public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
        {
            var body = actionContext.Request.Content.ReadAsStringAsync().Result;

是否有这样做的更有效的方法? 还是我读蚂蚁探查是否有误?

Answer 1:

多大内容? 请注意,你可能会看到很多的时间,因为你在呼唤同步,而不是异步这个网络通话。

你可能阅读的字符串较早异步和请求财产藏匿它。

或者你可以写一个格式化代替,然后用装饰[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;
    }
}

添加authroization过滤器(他们冲在最前面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

config.Filters.Add(new MyStringFilter());

ValuesController.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个字符)记得可以进入大对象堆,这将造成的对您的网站的性能造成严重破坏。 如果你的东西,这是很常见,把输入分解成类似字符串的字符串生成器/阵列或不连续的内存类似的东西。 见为什么大对象堆,为什么我们关心?



文章来源: ModelBinder Request.Content.ReadAsStringAsync performance