要创建一个接受参数来源于参数类型的任何类型的动作(多态参数) [英] To Create Action That Accepts a Parameter Of Any Type Derived From The Parameter Type (Polymorphic Parameter)

查看:151
本文介绍了要创建一个接受参数来源于参数类型的任何类型的动作(多态参数)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想建立一个动态结构,客户要求服务器的Web API。我曾尝试使用以下code来处理我的问题,但是,它不工作。


  

      
  1. 我如何发送一个泛型类型,比如<旅游> 服务

  2.   
  3. 如何更改服务器code(或都需要更改客户端/服务器)?

  4.   

PS:感谢您的耐心,如果你看过我到底问题。

客户端code

  VAR串=新的JavaScriptSerializer();
变种产品=新的行程(){travel_desc =SELECT * FROM出行};
变种jsonText = serializer.Serialize(产品);
VAR的客户=新的HttpClient();
client.BaseAddress =新的URI(HTTP://本地主机:65370 /);
client.DefaultRequestHeaders.Accept.Add(新MediaTypeWithQualityHeaderValue(应用/ JSON));
内容的StringContent =新的StringContent(jsonText,Encoding.UTF8,应用/ JSON);变种Z = client.PostAsync<旅游>(API / BB,产品,新JsonMediaTypeFormatter())结果。

服务器code,这是行不通的。

 公共IHttpActionResult邮政< T> (对象x),其中T:新的()
{
                ........................
}

的方式是好的,但我不知道如何发送< T>服务器

 公共IHttpActionResult邮政(对象x)
{
                ........................
}

错误消息结果
客户端呼叫服务器,服务器将收到错误消息状态code:404,ReasonPhrase:未找到

  VAR Z = client.PostAsync<旅游> (API / DD,产品,新JsonMediaTypeFormatter())结果。 <  - 客户端    公共类ddController< T> :ApiController {公共虚拟无效后(){...}}< ---服务器  //对不起所有,我的英语不是很好,所以我会尝试使用code告诉大家我多么希望
//格式的情况下,我将创建2个控制器时,我有2个型号(例如:用户/产品),如下(客户端)
                VAR一个= client.PostAsync(API /用户,用户,新JsonMediaTypeFormatter())结果。
                变种B = client.PostAsync(API /产品,产品,新JsonMediaTypeFormatter())结果。//与用户和产品控制器创建那么当后code应该像如下(服务器)
                公共IHttpActionResult Postusers(用户出行){}
                公共IHttpActionResult Postproduct(产品行程){}   //现在我只是想为像上面的follwing创建1控制器
                 变种B = client.PostAsync<用户/产品的方式>(API / all,则产品,新JsonMediaTypeFormatter())结果;(客户端)                 公共IHttpActionResult邮政< T>(对象的ForAll)其中T:新的(){}(服务器)


解决方案

JSON.NET,在Web API JSON序列,能够序列化对象时发送类型信息,并使用相同的信息反序列化。

这是它使用的伎俩是包括 $类型属性作为JSON对象的第一个属性。

如果你想使用这种技术,你需要有一个基类或接口,例如 ITravel ,继承其所有可能的类,并使用基类或接口的参数类型,像这样:

 公共接口ITravel
{
  公众诠释TravelId {搞定;组; }
}公共类TravelTypeA:ITravel
{
  公众诠释TravelId {搞定;组; }
  公共字符串目标{搞定;组; }
}公共类TravelTypeB:ITravel
{
  ...
}[HttpPost]
公共对象PostMeATravel(ITravel行程)
{
    //检查什么类型与旅游是或.GetType()
}

您还需要指示JSON包含的类型信息时,(反)序列 ITravel 的对象。 (<一href=\"http://stackoverflow.com/questions/12638741/deserialising-json-to-derived-types-in-asp-net-web-api/23999085#23999085\">JSON类型名处理):

  JsonSerializerSettings serializerSettings
  = GlobalConfiguration.Configuration.Formatters
    .JsonFormatter.SerializerSettings;serializerSettings.TypeNameHandling = TypeNameHandling.Auto;

然后你必须与后一个typeInformation JSON,像这样的:

  {
  $类型:'SampleApp.TravelTypeA,SampleApp',
  TravelId:22,
  目的地:'拉尔穆尼亚德多尼亚戈迪纳
}

当你这样做,JSON.NET将使用类型信息来创建一个 TravelTypeA 对象,并把它作为参数传递给动作,期望一个 ITravel 。里面的动作,您可以检查所接收到的参数的类型,如果你需要的话,像这样:如果(travel.GetType()==名TravelTypeA){...}

看这个Q&安培; A关于如何做到这一点,它是如何工作,以及更多的信息优势,这种方法做的另一种方式的弊端:<一href=\"http://stackoverflow.com/questions/12638741/deserialising-json-to-derived-types-in-asp-net-web-api/23999085#23999085\">Deserialising派生的Json类型Asp.Net的Web API

注意:您可以使用优秀的邮差补充Chrome浏览器测试Web API方法

I want to build a dynamic structure for a client to ask server in web API. I have tried to use the following code to deal with my question, however, it isn't working.

  1. How can I send a generic type like <travel> to service
  2. How can I change server code (or all need to change client/server)?

PS:Thank you for your patience if you have read my question to the end.

Client Code

var serializer = new JavaScriptSerializer();    
var product = new travel() { travel_desc = "select * from travel" };    
var jsonText = serializer.Serialize(product);    
var client = new HttpClient();    
client.BaseAddress = new Uri("http://localhost:65370/");     
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));    
StringContent content = new StringContent(jsonText, Encoding.UTF8, "application/json");     

var z = client.PostAsync<travel>("api/bb", product, new JsonMediaTypeFormatter()).Result;

Server Code, which is not working

public IHttpActionResult Post< T > (Object x) where T : new()    
{    
                ........................    
}

by the way it is okay but i don't know how to send < T > to server

public IHttpActionResult Post(Object x)    
{    
                ........................    
}     

Error message
Client call server, server will be getting an error message " StatusCode: 404, ReasonPhrase: 'Not Found' "

 var z = client.PostAsync < travel > ("api/dd", product, new JsonMediaTypeFormatter()).Result; <--client

    public class ddController< T > : ApiController {public virtual void Post() {   ... }  } <---server    





  // sorry all , my English isn't very well , so I will try to use code to tell everyone how i want 
// in format situations,I will create 2 controller when I have 2 models(ex: users/product) , as following (client)
                var a = client.PostAsync("api/users", users, new JsonMediaTypeFormatter()).Result;
                var b = client.PostAsync("api/product", product, new JsonMediaTypeFormatter()).Result;

//and then when the users and product controllers was created the post code should be like as following (server)
                public IHttpActionResult Postusers(users travel) {}
                public IHttpActionResult Postproduct(product travel) {}

   //now i just want to create 1 controller for above  like as follwing 
                 var b = client.PostAsync<users/product>("api/all", product, new JsonMediaTypeFormatter()).Result;(client)

                 public IHttpActionResult Post<T>(Object ForAll) where T : new() {} (server)

解决方案

JSON.NET, the Web API JSON serializer, is able to send type information when serializing an object, and use that same information to deserialize it.

The trick that it uses is including a $type property as the first property of the JSON object.

If you want to use this technique, you need to have a base class or an interface, for example ITravel, inherit all the possible classes from it, and use the base class or interface as the parameter type, like so:

public interface ITravel
{
  public int TravelId { get; set; }
}

public class TravelTypeA : ITravel
{
  public int TravelId { get; set; }
  public string Destination { get; set; }
}

public class TravelTypeB : ITravel
{
  ...
}

[HttpPost]
public object PostMeATravel(ITravel travel)
{
    // check what type is travel with "is" or ".GetType()"
}

You also need to instruct JSON to include type information when (de)serializing ITravel objects. (JSON TypeName Handling):

JsonSerializerSettings serializerSettings 
  = GlobalConfiguration.Configuration.Formatters
    .JsonFormatter.SerializerSettings;

serializerSettings.TypeNameHandling = TypeNameHandling.Auto;

And then you have to post a JSON with typeInformation, like this:

{
  $type: 'SampleApp.TravelTypeA, SampleApp',
  TravelId: 22,
  Destination: 'La Almunia de Doña Godina'
}

When you do so, JSON.NET will use the type information to create a TravelTypeA object, and pass it as parameter to the action, which expects an ITravel. Inside the action you can check the type of the received parameter if you need to do so, like this: if (travel.GetType().Name == "TravelTypeA") { ... }

Look at this Q&A for more information on how to do that, how it works, and advantages and drawbacks of this method and an alternative way of doing it: Deserialising Json to derived types in Asp.Net Web API

NOTE: you can use the excellent Postman complement for Chrome to test the Web API methods

这篇关于要创建一个接受参数来源于参数类型的任何类型的动作(多态参数)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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