通过多个复杂对象后/把的Web API方法 [英] Pass multiple complex objects to a post/put Web API method

查看:360
本文介绍了通过多个复杂对象后/把的Web API方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可以将部分请帮我知道如何从一个C#控制台应用程序与Web API控制器传递多个对象,如下图所示?



 使用(VAR的HttpClient =新System.Net.Http.HttpClient())
{
httpClient.BaseAddress =新的URI(ConfigurationManager.AppSettings [网址]);
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(新MediaTypeWithQualityHeaderValue(应用/ JSON));

VAR响应= httpClient.PutAsync(API /流程/ StartProcessiong,对象A,对象B);
}

我的Web API的方法是这样的:

 公共无效StartProcessiong([FromBody]内容的内容,[FromBody]配置配置)
{

}


解决方案

在网页API的当前版本的多次使用复杂的对象(如你的内容配置复杂的对象)的在Web API方法签名中是的不允许。我打赌好钱配置(你的第二个参数)总是回来为NULL。这是因为只有一个复杂的对象可以从主体解析为一个请求。出于性能的考虑,在Web API请求主体只允许访问和分析的一次。所以对于内容参数请求主体的扫描和解析发生之后,所有后续的身体解析将在NULL结尾。所以基本上:




  • 只有一个项目,可以用归因[FromBody] <。 / LI>
  • 任何数量的项目,可以用 [FromUri] 。



下面是的迈克失速的优秀的博客文章(老但戈尔迪!)。你要注意的项目4




下面是基本的规则,以确定是否一个参数被读出与模型结合或一个格式化器:



<醇>
  • 如果该参数上有没有属性,则判定纯粹作出关于该参数的。 NET类型。 简单类型使用模型绑定。复杂类型使用格式化。 A简单类型包括:时间跨度的DateTime 的Guid 小数字符串,或者说用的TypeConverter 从字符串转换。

  • 您可以使用 [FromBody] 属性来指定一个参数应该是从身体。

  • 您可以使用的参数或参数的类型[ModelBinder的] 属性来指定一个参数应该是模型界。这个属性还允许您配置模型绑定。 [FromUri] 的一个派生的实例[ModelBinder的] 专门配置一个模型绑定只查找在URI。

  • 正文只能读一次。所以,如果你在签名中有2个复杂的类型,其中至少有一个人必须有一个 [ModelBinder的] 属性就可以了。



  • 这是这些规则是静态的和可预测的一个关键的设计目标。



    之间的主要差异MVC和Web API是MVC缓存内容(如请求体)。这意味着,MVC的参数绑定可以通过身体反复搜索,寻找这些参数的部分。而在网页API,请求体( HttpContent )可能是一个只读的,无限的,非缓冲,非rewindable的流。




    您可以自己阅读本非常有用的文章的其余部分是这样,削减长话短说,你想要做的是目前无法以这种方式的(意思是,你必须得到创造性的)。接下来是不是一个解决方案,但有解决方法,只有一种可能性; 。还有其他的方法



    解决方案/解决方法



    声明:我没有用它自己,我只是知道理论的!)



    一个可能的解决方案是使用的 JObject 对象。这个对象提供专门用于JSON的设计了一个具体类型。



    您只需要调整的签字从身体接受只是一个复杂的对象,在 JObject ,姑且称之为的东西。然后,你需要手动解析JSON对象的属性和使用泛型来滋润的具体类型。



    例如,下面是一个例子quick'n'dirty给你一个想法:



    <预类=郎-CS prettyprint-覆盖> 公共无效StartProcessiong([FromBody] JObject东西)
    {
    //从JSON对象中提取你的具体对象。
    VAR内容=东西[内容] ToObject<内容及GT;();
    无功配置=东西[配置] ToObject<配置>();

    。 。 。 //现在做你的事!
    }



    我没有说有其他的方式,例如,你可以简单地包裹你的两个在超级对象对象的自己创作的,并传递到你的操作方法。或者,你可以简单地在URI提供其中一人消除在请求体两种复杂的参数的需要。或者......好吧,你明白了吧。



    让我再次重申,我没有尝试过任何这我自己,虽然理论上应该全部工作的


    Can some please help me to know how to pass multiple objects from a C# console app to Web API controller as shown below?

    using (var httpClient = new System.Net.Http.HttpClient())
    {
        httpClient.BaseAddress = new Uri(ConfigurationManager.AppSettings["Url"]);
        httpClient.DefaultRequestHeaders.Accept.Clear();
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));   
    
        var response = httpClient.PutAsync("api/process/StartProcessiong", objectA, objectB);
    }
    

    My Web API method is like this:

    public void StartProcessiong([FromBody]Content content, [FromBody]Config config)
    {
    
    }
    

    解决方案

    In the current version of Web API, the usage of multiple complex objects (like your Content and Config complex objects) within the Web API method signature is not allowed. I'm betting good money that config (your second parameter) is always coming back as NULL. This is because only one complex object can be parsed from the body for one request. For performance reasons, the Web API request body is only allowed to be accessed and parsed once. So after the scan and parsing occurs of the request body for the "content" parameter, all subsequent body parses will end in "NULL". So basically:

    • Only one item can be attributed with [FromBody].
    • Any number of items can be attributed with [FromUri].

    Below is a useful extract from Mike Stall's excellent blog article (oldie but goldie!). You'll want to pay attention to item 4:

    Here are the basic rules to determine whether a parameter is read with model binding or a formatter:

    1. If the parameter has no attribute on it, then the decision is made purely on the parameter's .NET type. "Simple types" use model binding. Complex types use the formatters. A "simple type" includes: primitives, TimeSpan, DateTime, Guid, Decimal, String, or something with a TypeConverter that converts from strings.
    2. You can use a [FromBody] attribute to specify that a parameter should be from the body.
    3. You can use a [ModelBinder] attribute on the parameter or the parameter's type to specify that a parameter should be model bound. This attribute also lets you configure the model binder. [FromUri] is a derived instance of [ModelBinder] that specifically configures a model binder to only look in the URI.
    4. The body can only be read once. So if you have 2 complex types in the signature, at least one of them must have a [ModelBinder] attribute on it.

    It was a key design goal for these rules to be static and predictable.

    A key difference between MVC and Web API is that MVC buffers the content (e.g. request body). This means that MVC's parameter binding can repeatedly search through the body to look for pieces of the parameters. Whereas in Web API, the request body (an HttpContent) may be a read-only, infinite, non-buffered, non-rewindable stream.

    You can read the rest of this incredibly useful article on your own so, to cut a long story short, what you're trying to do is not currently possible in that way (meaning, you have to get creative). What follows is not a solution, but a workaround and only one possibility; there are other ways.

    Solution/Workaround

    (Disclaimer: I've not used it myself, I'm just aware of the theory!)

    One possible "solution" is to use the JObject object. This objects provides a concrete type specifically designed for working with JSON.

    You simply need to adjust the signature to accept just one complex object from the body, the JObject, let's call it stuff. Then, you manually need to parse properties of the JSON object and use generics to hydrate the concrete types.

    For example, below is a quick'n'dirty example to give you an idea:

    public void StartProcessiong([FromBody]JObject stuff)
    {
      // Extract your concrete objects from the json object.
      var content = stuff["content"].ToObject<Content>();
      var config = stuff["config"].ToObject<Config>();
    
      . . . // Now do your thing!
    }
    

    I did say there are other ways, for example you can simply wrap your two objects in a super-object of your own creation and pass that to your action method. Or you can simply eliminate the need for two complex parameters in the request body by supplying one of them in the URI. Or ... well, you get the point.

    Let me just reiterate I've not tried any of this myself, although it should all work in theory.

    这篇关于通过多个复杂对象后/把的Web API方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆