要创建一个接受参数来源于参数类型的任何类型的动作(多态参数) [英] To Create Action That Accepts a Parameter Of Any Type Derived From The Parameter Type (Polymorphic Parameter)
问题描述
我想建立一个动态结构,客户要求服务器的Web API。我曾尝试使用以下code来处理我的问题,但是,它不工作。
- 我如何发送一个泛型类型,比如
<旅游>
服务
- 如何更改服务器code(或都需要更改客户端/服务器)?
块引用>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.
- How can I send a generic type like
<travel>
to service- 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 anITravel
. 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屋!