3

我创建了一个带有一些 POCO 类的 MVC 4 WebApi 应用程序,并使用 EF 创建了一个具有读/写等功能的快速默认控制器。

现在由于某种原因我不能让这两种方法一起工作,但是第一种方法是 EF 创建的。简而言之,我想通过 ID 和用户名查找用户。

    // GET api/xxx
    public User GetUser(string id)
    {
        User user = db.Users.Find(id);
        if (user == null)
        {
            throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
        }
        return user;
    }

以上工作。这不起作用。

    // GET api/xxx
    public User GetUserByUsername(string username)
    {
        var user = db.Users.First(s => s.Username == username);
        if (user == null)
        {
            throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
        }

        return user;
    }

但是通过将其更改为以下内容并将一些添加到 webapi 配置中,然后以下工作:

    // GET api/xxx
    [HttpGet]
    [ActionName("username")]
    public User GetUserByUsername(string id)
    {
        var user = db.Users.First(s => s.Username == id);
        if (user == null)
        {
            throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
        }

        return user;
    }

并将 WebApiConfig 更改为:

      config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
        // Action-name
        config.Routes.MapHttpRoute(
            name: "ActionApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        ); 

我想知道为什么以前的方法不能一起工作(第一个和第二个),如果可能的话我可以做些什么来让它工作。我很确定它有一些东西,因为不能创建类似的方法似乎有点奇怪。

4

3 回答 3

3

因为 Web API 只查找方法是“GET”这一事实,并在方法名称中查找“get”字样。由于您的两个方法都具有“get”并且都接受单个字符串参数,因此控制器可能会解析到它找到的第一个参数,并且由于“id”是默认路由的一部分,因此它会与您的 GetUser 方法一起返回。

您也可以尝试为“用户名”添加路由:

config.Routes.MapHttpRoute(
        name: "ActionApi",
        routeTemplate: "api/{controller}/{username}",
        defaults: new { username = RouteParameter.Optional }
    ); 

编辑:尝试查看这些文章以了解路由如何与 Web API 一起使用。它不同于常规的 MVC 控制器。

http://www.asp.net/web-api/overview/web-api-routing-and-actions

于 2013-03-14T16:05:14.197 回答
0

这:

var user = db.Users.First(s => s.Username == id);

如果没有找到具有该 id 的用户,将导致异常

但是这个:

这:

var user = db.Users.FirstOrDefault(s => s.Username == id);

将返回null

于 2013-03-14T15:58:15.393 回答
0

通过在 DefaultApi 之后添加新的路由规则使其工作,

// Routing by Action-name
config.Routes.MapHttpRoute(
    name: "ActionApi",
    routeTemplate: "api/{controller}/{action}/{username}",
    defaults: new { username = RouteParameter.Optional }
);

并将方法更改为以下内容:

// GET api/xxx/username
[ActionName("username")]
public User GetUserByUsername(string username)
{
    var user = db.Users.FirstOrDefault(s => s.Username == username);
    if (user == null)
    {
        throw new HttpResponseException(
            Request.CreateResponse(HttpStatusCode.NotFound));
    }

    return user;
}

我认为我尝试了太多并且很傻,但现在看起来很清楚。

通过在我应用到 routeTemplate 的地方添加一个新路由{action}是有意义的,因为我可以添加一个属性[ActionName("username")]。然后我可以浏览localhost:xxxxx/api/xxx/2AND localhost:xxxxx/api/xxx/username/bob,这使得两个 GET 方法都可以工作,因为第二个路由规则接受一个操作。

@Rob,感谢您的链接和提示,感谢!

于 2013-03-15T10:43:30.940 回答