通用Web Api方法 [英] Generic Web Api method
问题描述
我有一些像 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屋!