【问题标题】:How to return different types of model from a WebAPI controller action?如何从 WebAPI 控制器操作返回不同类型的模型?
【发布时间】:2018-01-11 12:22:37
【问题描述】:

我有一个这样的控制器

    [ResponseType(typeof(List<InboxPatientModel>))]
    [Route("~/api/Messages/search")]
    public IHttpActionResult GetSearch(string serchTerm = "", string messageFor = "p")
    {
        try
        {
            if(messageFor == "p")
            {
                var inboxMessages = MessageToPatientList.Get(serchTerm);
                return Ok(inboxMessages);
            }
            else
            {
                var outboxMessages = MessageToDoctorList.Get(serchTerm);
                return Ok(outboxMessages);
            }
        }
        catch (Exception ex)
        {
             //some code for exception handling....
        }
    }

这里MessageToPatientList.GetMessageToDoctorList.Get返回不同类型的列表说InboxPatientModelInboxDoctorModel

是否可以用[ResponseType(...)]来装饰action,使其可以是动态的并且可以返回不同类型的列表?

【问题讨论】:

  • ResponseType 仅在请求自动 API 描述时由 ApiExplorer 用于文档目的。它对请求的处理没有影响。话虽如此,您可以使用多个 ResponseType 属性,即[ResponseType(typeof(List&lt;InboxPatientModel&gt;)), ResponseType(typeof(List&lt;InboxDoctorModel&gt;))]

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


【解决方案1】:

您可以合并不同类型的列表;

public class PatientModel
{
    public List<InboxPatientModel> Patients { get; set; }

    public List<InboxDoctorModel> Doctors { get; set; }
}

[ResponseType(typeof(PatientModel))]
[Route("~/api/Messages/search")]
public IHttpActionResult GetSearch(string serchTerm = "", string messageFor = "p")
{
    try
    {
        var patientModel = new PatientModel();
        if (messageFor == "p")
        {
            var inboxMessages = MessageToPatientList.Get(serchTerm);
            patientModel.Patients = inboxMessages;
        }
        else
        {
            var outboxMessages = MessageToDoctorList.Get(serchTerm);
            patientModel.Doctors = inboxMessages;
        }
        return Ok(patientModel);
    }
    catch (Exception ex)
    {
        //some code for exception handling....
    }
}

【讨论】:

    【解决方案2】:

    您的代码将运行良好。 [ResponseType] 属性仅用于为 Web API 文档页面和 Swagger 等工具提供提示。

    虽然该属性的AttributeUsage 属性中有AllowMultiple=true,但我认为那些文档工具不支持这一点。

    他们不应该这样做。根据月亮的大小、星期几或某些参数的值从 API 返回不同的类型,实现起来很麻烦,记录也很麻烦,消费也很麻烦。

    改为考虑审查设计。为什么消息的实际类型会根据接收者的身份而改变?这两种消息有什么不同

    相反,找到他们共享的属性。然后提取一个基类,比如Message,并用属性[ResponseType(typeof(Message))] 装饰方法。

    【讨论】:

      【解决方案3】:

      在搜索医生和患者时,URL 已经不同,因此单一操作没有任何好处。

      只需编写两个操作“GetDoctors”和“GetPatients”,它们会返回您想要的类型。

      [ResponseType(typeof(List<InboxPatientModel>))]
      [Route("~/api/Messages/searchpatients")]
      public IHttpActionResult GetPatients(string searchTerm = "")
      {
      }
      
      [ResponseType(typeof(List<InboxDoctorModel>))]
      [Route("~/api/Messages/searchdoctors")]
      public IHttpActionResult GetDoctors(string searchTerm = "")
      {
      }
      

      【讨论】:

      • 实际上InboxPatientModel 显示收件箱项目,InboxDoctorModel 显示患者邮箱中已发送/草稿项目。这就是保持单一动作的原因。
      • 但无论如何,这些东西的 URL 不同 - messageFor 不同。
      • 我实际上知道这种方法,但我想坚持使用单一方法以简化客户。
      【解决方案4】:

      每个资源(患者和医生)都应该有自己的控制器操作。我会这样做:

      1) 创建两个不同的控制器操作:一个用于 InboxPatientModel,另一个用于 InboxDoctorModel。

      2) 在客户端,您根据“messageFor”确定需要调用哪个控制器操作。

      3) 每个控制器操作都有不同的 ResponseType。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-12
        • 2013-06-26
        • 1970-01-01
        相关资源
        最近更新 更多