【问题标题】:To Create Action That Accepts a Parameter Of Any Type Derived From The Parameter Type (Polymorphic Parameter)创建接受从参数类型派生的任何类型参数的操作(多态参数)
【发布时间】:2015-05-12 02:05:30
【问题描述】:

我想为客户端构建一个动态结构以在 Web API 中询问服务器。我尝试使用以下代码来处理我的问题,但是它不起作用。

  1. 如何向服务发送像 <travel> 这样的泛型类型
  2. 如何更改服务器代码(或都需要更改客户端/服务器)?

PS:如果您将我的问题读到最后,感谢您的耐心等待。

客户代码

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;

服务器代码,不起作用

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

顺便说一句没关系,但我不知道如何发送到服务器

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

错误信息
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)

【问题讨论】:

  • 究竟是什么不工作?
  • 嗨 Kamo 客户端无法触发服务器 POST 事件
  • 你好 Konamiman : 这对我来说不起作用,你有其他方法吗,谢谢
  • 嗨@Konamiman,很抱歉打扰你,我很久没有使用Stack Overflow,但现在我无法发送任何东西,我不知道我该怎么办,因为我已经尝试过了修改了我所有的问题,但是“”不起作用,所以我聪明的人可以帮助我,再次抱歉,希望你能帮我一个忙,谢谢,威利

标签: c# asp.net asp.net-mvc asp.net-web-api parametric-polymorphism


【解决方案1】:

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

它使用的技巧是将 $type 属性作为 JSON 对象的第一个属性。

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

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()"
}

您还需要指示 JSON 在(反)序列化 ITravel 对象时包含类型信息。 (JSON TypeName Handling):

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

serializerSettings.TypeNameHandling = TypeNameHandling.Auto;

然后你必须发布一个带有 typeInformation 的 JSON,像这样:

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

当您这样做时,JSON.NET 将使用类型信息创建一个 TravelTypeA 对象,并将其作为参数传递给操作,该操作需要一个 ITravel。如果需要,可以在操作中检查接收到的参数的类型,如下所示:if (travel.GetType().Name == "TravelTypeA") { ... }

查看此问答以获取有关如何执行此操作、其工作原理以及此方法的优缺点以及另一种执行方法的更多信息:Deserialising Json to derived types in Asp.Net Web API

注意:您可以使用 Chrome 的优秀 Postman 补充来测试 Web API 方法

【讨论】:

  • 嗨,JB,你能不能给我一个简短的示例,包括客户端/服务器站点,我会感谢你为我做这件事,再次感谢
  • 我在引用的问答中获得了足够的信息:将 JSON.NET 配置添加到 AppStart 文件夹的任何引导类。创建一个控制器、一个接口和两个类,就像我在这个答案中展示的那样。最后,向这个控制器发出一个 POST 请求,使用属性 od TravelTypeA 并添加 $type: MyNamespace.TravelTypeA, MyAsssemblyName(完全限定的类型名称)作为 JSON 对象的第一个属性。您的 POST 操作将收到 TravelTypeA 的实例。如果您在实施此操作时遇到一些具体问题,请告诉我。用chrome的邮递员测试一下
  • 嗨,JB,也许这对我来说太难了,你能帮我给我更多的参考网址吗,因为我已经尝试过如上所述你给我参考我的代码,“公共类 TravelTypeA:ITravel {}"
  • 我在回答中添加了更多信息。请看一下
  • JB.真的谢谢你的帮助,我在上下文后面放了另一个代码,你介意再看一遍吗,对不起我愚蠢的英语,也许我没有为你清楚地描述我的问题,你能理解我的问题是什么,或者事实上我已经解决了我的问题,如果是的话,我会尝试更多次,这对我来说很难。再次感谢您的好意
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-18
  • 2018-12-10
  • 2011-10-09
相关资源
最近更新 更多