通用Web Api方法 [英] Generic Web Api method

查看:182
本文介绍了通用Web Api方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些像 CustomerModel CustomerDetailsModel 的类,这些类从 ModelBase



另外,我不想为每个模型类型引入子类。



在一种情况下,有一个post方法foreach。

所以我可以手动创建多个路由来调用一个方法,看起来像

  Handle< T>(T model)其中T:ModelBase 



他们只在被调用的路径上有所不同。例如:

  baseurl / api / customer => CustomerModel 
baseurl / api / customerdetails => CustomerDetailsModel

我想实现一个通用的web api方法,如$ / b
$ b

  [HttpPost] 
void Post< T>(T model)其中T:ModelBase

如果我简单地创建一个泛型方法,那么我得到一个异常,它告诉我web api方法不能使用泛型方法。但是前一段时间,我已经看到一个使用某种自定义查找机制来处理这个问题的web api v1的实现。但我无法弄清楚它。



作为一种解决方法,我创建了一个callwrapper,它确定了类型并调用了一个内部泛型方法,但这感觉很难看。

  public async Task< IHttpActionResult> Post(string id,string moduleType)
{
await AsyncGenericCallWrapper(moduleType);
...

有了上面提到的通用控制器将会有很多黄油。 / b>

  private async Task AsyncGenericCallWrapper(string moduleType)
{
Type type = GetModuleType(moduleType);
var content = await Request.Content.ReadAsStringAsync();
var instance = JsonConvert.DeserializeObject(content,type);

MethodInfo method = this.GetType()。GetMethod(InternalGenericMethod,BindingFlags.NonPublic | BindingFlags.Instance);
MethodInfo generic = method.MakeGenericMethod(type);
var result = generic.Invoke(this,new object [] {instance})as Task;

等待结果;





$ b

我可以通过自定义属性映射像

GenericRoute(/ customer,typeof(CustomerModel)]
[GenericRoute(/ customerDetail,typeof(CustomerDetailModel) ]
void Post< T>(T model)其中T:ModelBase

可以为每个属性创建路由,但仍然可以调用该方法,因为它是通用的,我也不知道如何干扰反序列化机制。

GenericWebAPiMethod?

解决方案

这种方法的问题在于Web API不知道如何反序列化对象。



与其使用泛型方法,您可以创建一个通用控制器。



假设您的模型如下所示: / p>

  public abstract class ModelBase {} 

public class CustomerModel:ModelBase {}

public class CustomerDetailsModel:ModelBase {}

您可以编写一个通用控制器处理继承自ModelBase的类:

  public class ModelBaseController< T> :ApiController其中T:ModelBase 
{
[HttpPost]
public void Post(T模型)
{
...
}
}

public class CustomerModelController:ModelBaseController< CustomerModel>
{
}

公共类CustomerDetailsModelController:ModelBaseController< CustomerDetailsModel>
{
}


I've some classes like CustomerModel or CustomerDetailsModel which are inherting from ModelBase.

Also i don't want to introduce subclasses for each modeltype.

In one case have a post method foreach.

So i could manually create multiple routes to call a method which looks like

Handle<T>(T model) where T : ModelBase

They only differ in the path the were called. For example:

baseurl/api/customer => CustomerModel
baseurl/api/customerdetails => CustomerDetailsModel

I want to implement a generic web api method like

[HttpPost]
void Post<T>(T model) where T : ModelBase

If I simply create a generic method i got an exception which tells me that the web api method could not have generic methods. But sometime ago I've seen an implementation with web api v1 using some kind of custom lookup mechanisms to handle this. But i can't figure out it anymore.

As a workaround I created a callwrapper which determines the type and invokes a internal generic method, but this feels quite ugly

 public async Task<IHttpActionResult> Post(string id, string moduleType)
        {
            await AsyncGenericCallWrapper(moduleType);
...

It would be much butter to have the above mentioned generic controllerr.

  private async Task AsyncGenericCallWrapper(string moduleType)
        {
            Type type = GetModuleType(moduleType);
            var content = await Request.Content.ReadAsStringAsync();
            var instance = JsonConvert.DeserializeObject(content, type);

            MethodInfo method = this.GetType().GetMethod("InternalGenericMethod", BindingFlags.NonPublic | BindingFlags.Instance);
            MethodInfo generic = method.MakeGenericMethod(type);
            var result = generic.Invoke(this, new object[] { instance }) as Task;

            await result;
        }

I can image to have a custom Attribute which maps the types like

[GenericRoute("/customer", typeof(CustomerModel)]
[GenericRoute("/customerDetail", typeof(CustomerDetailModel)]
void Post<T>(T model) where T : ModelBase

With this i could create routes for each attribute, but still the method now get invoked as it is generic , nor i know how to interfer the deserialization mechanism

Can anyone tell me how to implement that GenericWebAPiMethod?

解决方案

The problem with this approach is that the Web API does not know how to deserialize the object.

Rather than having a generic method, you can create a generic controller.

Let's say your model is like that:

public abstract class ModelBase{ }

public class CustomerModel : ModelBase {}

public class CustomerDetailsModel: ModelBase { }

You can write a generic controller to deal with classes that inherits from ModelBase :

public class ModelBaseController<T> : ApiController where T : ModelBase 
{
    [HttpPost]
    public void Post(T model)
    {
        ...
    }
}

public class CustomerModelController : ModelBaseController<CustomerModel>
{
}

public class CustomerDetailsModelController : ModelBaseController<CustomerDetailsModel>
{
}

这篇关于通用Web Api方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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