Web API通用动作 [英] Web API Generic Action

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

问题描述

我有一个http动作,它将需要采用两个不同的对象模型.该实现将查看两个模型对象,并知道此时该怎么做.我可以使用通用对象吗?

I have a http Action that will needs to take in two different object model. The Implementation looks at the two model object and know what to do at that point. Can I use a generic object?

[HttpPost]
public IHttpActionResult InsertData(string accessKey, [FromBody] T content)
{
    try
    {
        MobileAppService ms = new MobileAppService();
        ResultStatus resultStatus = ms.ProcessAppLogging(t);
        return Ok(resultStatus.ResultCode);
    }
    catch (Exception e)
    {
        Elmah.ErrorSignal.FromCurrentContext().Raise(e);
    }
}

推荐答案

具有通用操作方法的控制器

对于框架的默认实现,否,您不能执行以下操作:

With default implementations of the framework, No, you cannot have such action:

public IHttpActionResult InsertData([FromBody] T model)

这是您收到的例外情况:

This is the exception which you receive:

无法在控制器上调用操作方法"XXXX""XXXX"是因为动作方法是通用方法.

Cannot call action method 'XXXX' on controller 'XXXX' because the action method is a generic method.

但是该框架非常可扩展,如果您对

But the framework is very extensible and if you get a very good understanding of Routing and Action Selection in ASP.NET Web API and learn how routing, controller selection, action selection, parameter binding and action invocation work, then you can implement some customization for the framework to support generic action method selection and invocation.

在您的自定义逻辑中,要能够在运行时执行操作,您需要在运行时解析 T .为此,您可以依靠属性将其限制为某些已知类型,也可以依靠某些上下文信息(例如,路由数据,标头值,某些特殊值,例如主体中的 $ type 等).

In your custom logic, to be able to execute the action in run-time, you need to resolve T at run-time. To do so, you can rely on attributes to limit it to some known types or you can rely on some context information like route data, header values, some special values like $type in body an so on.

提供用于处理通用操作方法的自定义实现对于本文而言过于广泛.就是说,让我分享其他解决方案.

Providing a custom implementation to handle generic action method is too broad for this post. That said, let me share other solutions.

从通用基本控制器派生

您可以有一个基本的通用控制器,然后有两个从该基本控制器派生的非通用控制器,并通过在基本控制器中实现的单一方法来处理请求.我认为您已经看过此帖子,它已经建议了相同的解决方案:

You can have a base generic controller then having two non-generic controllers derived from the base controller and handle the request by a single method which is implemented in the base controller. I assume you have seen this post which has already suggested the same solution:

public class MyBaseController<T> : ApiController
{
    public IHttpActionResult InsertData([FromBody] T model)
    {
        //Write the generic code here, for example:
        dbContext.Set<T>().Add(model);
        dbContext.SaveChanges();
        return some value;            
    }
}

然后:

public class ProductController : MyBaseController<Product> { }
public class CustomerController : MyBaseController<Customer> { }

依靠 dynamic 并稍后根据上下文信息解析类型

Rely on dynamic and resolve the type later based on context information

另一个选项具有以下操作方法:

Another option is having the following action method:

public IHttpActionResult InsertData([FromBody] dynamic model)

然后基于某些上下文信息,例如路由值,标头值,某些特殊值(例如主体中的 $ type 等),您可以解析模型类型并调用您的私有泛型方法:

Then based on some context information like route values, header values, some special values like $type in body an so on, you can resolve model type and call your private generic method:

public IHttpActionResult InsertData([FromBody] dynamic model)
{
    Type t = resolve type base on context information
    object data = create an instance of t base on the model values;

    var method = this.GetType().GetMethod(nameof(InsertDataPrivate),
        BindingFlags.NonPublic | BindingFlags.Instance);
    var result = (int)method.MakeGenericMethod(t)
       .Invoke(this, new object[] { data });

    return Ok(result);
}
private int InsertDataPrivate<T>(T model) where T
{
    //Write the generic code here, for example:
    dbContext.Set<T>().Add(model);
    dbContext.SaveChanges();
    return some value;
}

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

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