C# 方法返回多个对象

C# 方法返回多个对象,c#,asp.net-mvc,asp.net-mvc-4,asp.net-web-api,asp.net-mvc-routing,C#,Asp.net Mvc,Asp.net Mvc 4,Asp.net Web Api,Asp.net Mvc Routing,我有一个MVC4项目,它使用来自WebAPI1项目的服务 在这里,我需要一个服务方法,在此方法中,我根据操作传递一个id和一个名为action的字符串 服务应该从表中获取数据。在这里,我将有不同的情况下,根据行动 因此,如果我的操作是person,它应该转到person表,并根据传递的id返回列表 如果操作是电子邮件,则应根据传递的id从电子邮件表中获取数据,并应返回列表 由于我的返回类型在每种情况下都不同,是否可以从单个方法实现?如果是的话,我的返回类型是什么 public Email Get

我有一个MVC4项目,它使用来自WebAPI1项目的服务

在这里,我需要一个服务方法,在此方法中,我根据操作传递一个id和一个名为action的字符串 服务应该从表中获取数据。在这里,我将有不同的情况下,根据行动

因此,如果我的操作是person,它应该转到person表,并根据传递的id返回列表

如果操作是电子邮件,则应根据传递的id从电子邮件表中获取数据,并应返回列表

由于我的返回类型在每种情况下都不同,是否可以从单个方法实现?如果是的话,我的返回类型是什么

public Email GetEmail(int id)
{
    Email email = db.Emails.Find(id);
    if (email == null)
    {
        throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
    }

    return email;
}


public List<Email> GetEmailByPerson(int personid)
{
    List<Email> email = db.Emails.Where(n => n.PersonID == personid).ToList();

    if (email == null)
    {
        throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
    }

    return email;
}

public Person GetPerson(int id)
{
    Person person = db.Persons.Find(id);
    return person;
}
控制器操作的代码为:

[ActionName=EmailsByPersonID]
public IEnumerable<Email> GetEmailsByPersonID(int personid)
{
    var emails = db.Emails.Where(n => n.Personid == personid).ToList();

    if (emails == null)
    {
        throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
    }

    return emails.AsEnumerable();
}
[ActionName=EmailsByPersonID]
public IEnumerable GetEmailsByPersonID(int personid)
{
var emails=db.emails.Where(n=>n.Personid==Personid.ToList();
如果(电子邮件==null)
{
抛出新的HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
返回电子邮件。AsEnumerable();
}

我在web api.config文件中做了这些更改,并用操作名EmailByPerson修饰了我的方法,服务调用是

我不喜欢这种方法,但您不要求我们对此发表意见,而是问一个特定的问题。这个问题的答案是肯定的,这是可能的

您可以为此目的使用HttpResponseMessage:

public HttpResponseMessage GetXx(string type, int id)
{
    switch(type)
    {
        case "xx":
            Type1 obj1 = <your logic>;
            return Request.CreateResponse(HttpStatusCode.OK, obj1);
        case "yy":
             ....
}
public HttpResponseMessage GetXx(字符串类型,int-id)
{
开关(类型)
{
案例“xx”:
类型1 obj1=;
返回请求.CreateResponse(HttpStatusCode.OK,obj1);
案例“yy”:
....
}

有几种方法可以解决这个问题

  1. You can use [RoutePrefix("api/Service")] for your controller and [Route("User")] and [Route("Email")] , 
您也应该能够调用web api api/服务/用户(获取、发布、放置、删除), 同样的事情也发生在你的电子邮件中

 2. you can create IModel/IResult/SuperClass for your User/Email, and your web api method would be like IEnumerable<IModel> Get(string entityType) or 
 IModel Get(string entityType,int id)
2.您可以为您的用户/电子邮件创建IModel/IResult/SuperClass,您的web api方法类似于IEnumerable Get(string entityType)或
IModel Get(字符串entityType,int-id)
希望这能起作用。

使用此模板-

public class MyController : ApiController
{
    public string GetName(string id)
    {
        return id;
    }

    public string GetNameById(string id)
    {
        return id;
    }
}

GlobalConfiguration.Configuration.Routes.MapHttpRoute
        ("default","api/{controller}/{action}/{id}",new { id = RouteParameter.Optional });
然后像这样调用api-

http://localhost:port/api/My/GetName/12
http://localhost:port/api/My/GetNameById/12
至少对我有用。:)

更新

你也可以这样做-

public class CustomActionInvoker : ApiControllerActionSelector
{
    public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
    {
        if (controllerContext == null)
            throw new ArgumentNullException("controllerContext");

        var routeData = (string)controllerContext.RouteData.Values["optional"];
        if (!string.IsNullOrWhiteSpace(routeData))
        {
            var actionInfo = controllerContext.ControllerDescriptor.ControllerType
                .GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly).ToList();
            var methodInfo = actionInfo.Where(a => a.Name.Contains(routeData)).FirstOrDefault();
            if (methodInfo != null)
            {
                return new ReflectedHttpActionDescriptor(controllerContext.ControllerDescriptor, methodInfo);
            }
        }
        return base.SelectAction(controllerContext);
    }
}
在配置中-

 GlobalConfiguration.Configuration.Routes.MapHttpRoute("default", "api/{controller}/{optional}/{id}", new { id = RouteParameter.Optional });

  GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpActionSelector), new CustomActionInvoker());
并将api调用更改为-

http://localhost:port/api/My/Email/12

可能是上一个示例完全遵循了这种开箱即用的方法。

我不明白为什么不将其构建为两个web api调用。由于每个调用都比较简单,所以总体实现工作量较少。一刀切=非常适合每个人。编写两个方法。我无法在同一个控制器中调用两个get/post方法。我使用的是web api1.如果我使用相同的参数int:ID生成多个方法,它总是调用一个get方法。我读过关于属性映射的内容。但我无法在WebAPI 1中实现这一点。有趣的是,您可以控制api的路由,并且您可以实际确定要调用的操作。我可以看看您的路由模板吗?它是默认模板公共静态无效寄存器(HttpConfiguration config){config.Routes.MapHttpRoute(名称:“DefaultApi”,路由模板:“api/{controller}/{id}”,默认值:new{id=RouteParameter.Optional});}换句话说,添加第二个参数来指示返回类型的类型。这将避免您执行多个操作。我只是解释一下您的方法。您添加了
字符串类型
,这样您就不需要其他操作方法,但只编写了一个操作方法。我之前尝试了第一个方法,但没有找到[Route]属性。我正在使用web api1。我认为这是web api 2config.Routes.MapHttpRoute(名称:“ActionApi”,routeTemplate:“api/{controller}/{EmailsByPersonID}/{id}”,默认值:new{id=RouteParameter.Optional})中添加的功能;不。保留这个默认路由。我很困惑。现在我在webapi.config文件中有两个路由配置。你能详细说明我的编辑吗。您应该将调用传递给api,即来自控制器的实际操作名称。谢谢,Amit。我厌倦了第一种方法。它起作用了。但我还必须更改所有其他服务调用,以包括操作名称,并指定Get和Set。是否可以使用一个没有操作名称的默认服务调用和方法的另一个路由配置我有几个签名相同的get/post方法。。
http://localhost:port/api/My/Email/12