在.NET Web API POST/PUT方法中使用继承的类 [英] Using inherited classes in .NET web API POST/PUT method

查看:106
本文介绍了在.NET Web API POST/PUT方法中使用继承的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不知道如何在Web API控制器中处理继承的类.我必须创建一个 API控制器以创建和更新数据库中的继承对象.

I can't figure out how I can work with inherited classes in an web API controller. I have to create only one API controller to create and update inherited objects in the database.

类似于我的模型(所有这些模型都具有一个Dto):

Similar to my models (to all these models exists a Dto):

public class Animal
{
    public virtual string Name {get; set;} // e.g. Harry
    public virtual string Type {get; set;} // e.g. Dog
}

public class AnimalDto
{
    public string Name;
    public Type Type;
}

public class Dog : Animal
{
    public virtual bool CanBark {get; set;} // e.g. true
}

public class Cat : Animal
{
    public virtual bool CanMiau {get; set;}
}

我已经尝试在控制器中使用json了.但是总是有json null

I already tried to use the json in the controller. But there was the json always null

[HttpPost]
public ActionResult Post([FromBody]JObject json)
{
    // idk what's going here?!
}

现在是我的控制器,但这切断了Dog或Cat模型的所有属性

My controller now, but that cuts off all attributes of Dog or Cat model

[HttpPost]
public ActionResult Post([FromBody]AnimalDto animal)
{
    // idk what's going here?!
}

我正在使用.NET Core 2.0

I'm using .NET Core 2.0

有什么想法吗?谢谢!

编辑

如果我想动态地执行此操作怎么办?像这样:

What if I want to do this dynamically? Something like:

var animal = json.ToObject<Animal>();
var actualAnimal = json.ToObject<typeof(animal.Type)>();

我该怎么做?

推荐答案

我已经尝试在控制器中使用json了.但是json总是为空

I already tried to use the json in the controller. But there was the json always null

总是得到null的原因是您没有声明正确的Type.您不应该通过[FromBody]接收string类型的动物.

The reason why you always get null is that you didn't declare the correct Type. You're not supposed to receive a string type of animal via [FromBody].


    [HttpPost]
    public ActionResult Post([FromBody]string json)
    public ActionResult Post([FromBody]Dog dog)
    {
        // now you get the dog
    }

请注意,如果您根本不关心类型,则一种方法是声明dynamic类型:

As a side note, if you don't care the type at all, one approach is to declare a dynamic type:

[HttpPost]
public IActionResult Post([FromBody] dynamic json)
{
    return new JsonResult(json); 
}

在这种情况下,动态类型为JObject,您可以将它们强制转换为任意类型:

In this scenario, the dynamic type is JObject, you could cast them to any type as you like:

public IActionResult Post(/*[ModelBinder(typeof(AnimalModelBinder))]*/[FromBody] JObject json)
{
    var animal=json.ToObject<Animal>();
    var dog = json.ToObject<Dog>();
    return new JsonResult(json); 
}

现在是我的控制器,但这切断了Dog或Cat模型的所有属性

My controller now, but that cuts off all attributes of Dog or Cat model

如果要使用AnimalDto,则应使属性可访问:

If you would like to use the AnimalDto, you should make the properties accessible:


    public class AnimalDto
    {
        public string Name;
        public string Name{get;set;}
        public string Type;
        public string Type{get;set;}
    }

如果我想动态地执行此操作怎么办?像这样:

What if I want to do this dynamically? Something like:

var animal = json.ToObject<Animal>();
var actualAnimal = json.ToObject<typeof(animal.Type)>();

如果我们想将json转换为某种特定类型,我们首先必须知道目标Type是什么.但是您的animal.Type属性是String的类型,并且可能是约定俗成的字符串.如果此Type属性恰好是没有名称空间的类名,例如

If we want to cast the json to some particular type, we must firstly know what the target Type is . But your animal.Type property is a type of String, and that might be a by-convention string. If this Type property is exactly the class name without namespace , e.g.

  • Cat.Type必须等于Cat
  • Dog.Type必须等于Dog
  • Fish.Type必须等于Fish
  • Cat.Type must equals Cat
  • Dog.Type must equals Dog
  • Fish.Type must equals Fish

然后您可以使用Type.GetType()解析目标类型.例如:

then you can you use Type.GetType() to resolve the target type. For example :

// typename : the Animal.Type property
// ns : the namespace string 
private Type ResolveAnimalType(string typename,string ns){
    if(string.IsNullOrEmpty(ns)){ ns = "App.Models";}
    typename= $"{ns}.{typename}";
    var type=Type.GetType(
        typename,
        assemblyResolver:null,  // if you would like load from other assembly, custom this resovler
        typeResolver: (a,t,ignore)=> a == null ? 
            Type.GetType(t, false, ignore) : 
            a.GetType(t, false, ignore),
        throwOnError:true,
        ignoreCase:false
    );
    return type;
}

无论如何,您可以根据自己的需求自定义我们解决目标Type的方式.然后通过方法ToObject<T>() 将json对象投射到所需的Type中:

Anyway, you could custom the way we resolve the target Type according to your own needs. And then cast the json object to your wanted Type by method ToObject<T>():

[HttpPost]
public IActionResult Post([FromBody] JObject json)
{
    var typename = json.Value<string>("type");
    if(String.IsNullOrEmpty(typename)) 
        ModelState.AddModelError("json","any animal must provide a `type` property");
    
    // resolve the target type
    var t= ResolveAnimalType(typename,null);

    // get the method of `.ToObject<T>()`
    MethodInfo mi= typeof(JObject)
        .GetMethods(BindingFlags.Public|BindingFlags.Instance)
        .Where(m=> m.Name=="ToObject" && m.GetParameters().Length==0 && m.IsGenericMethod  )
        .FirstOrDefault()
        ?.MakeGenericMethod(t); // ToObject<UnknownAnimialType>()

    var animal = mi?.Invoke(json,null);
    return new JsonResult(animal); 
}

这篇关于在.NET Web API POST/PUT方法中使用继承的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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