【问题标题】:WebAPI accepts broken JSON send via FiddlerWebAPI 接受通过 Fiddler 发送的损坏的 JSON
【发布时间】:2013-04-23 16:44:39
【问题描述】:

出于某种原因,我可以将这两个 JSON 请求发送到我的 WebAPI,它会接受并创建一个用户。一个带双引号,一个不带。

{"Username":"Bob", "FirstName":"Foo", "LastName":"Bar", "Password":"123", "Headline":"Tuna"}

{Username:"Bob", FirstName:"Foo", LastName:"Bar", Password:"123", Headline:"Tuna"}

这是创建用户的方法。

    // localhost:12345/api/controller/create
    [ActionName("create")]
    public HttpResponseMessage PostUser(User user)
    {
        if (ModelState.IsValid)
        {
            db.Users.Add(user);
            db.SaveChanges();

            HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, user);
            response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = user.UserId }));
            return response;
        }
        else
        {
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
        }
    }

但是,我可以在 URL 末尾没有 /create 的情况下发出成功的 POST 请求。我假设 POST 请求成功的原因是因为无论操作名称是否存在,它都会在方法名称中搜索Post

所以我的问题是,动作名称的目的是什么?我怎样才能使它成为 URL 中的必须项?还有为什么它同时接受 JSON 请求,我怎样才能让它接受一个或另一个。

编辑:

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

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

感谢您的宝贵时间

/两次

【问题讨论】:

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


    【解决方案1】:

    我怎样才能使它成为 URL 中的必须项?

    通过更改~/App_Start/WebApiConfig.cs 中的路由定义并让动作名称显式出现在您的路由中:

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

    还有为什么它同时接受 JSON 请求以及如何让它接受其中一个。

    因为 Web API 使用 JSON.NET 作为接受这两者的 JSON 序列化程序。

    【讨论】:

    • 我有两个配置路由,我已经用它们更新了我的帖子。为什么这行不通?第二个配置,在路由中有一个动作,只有 username 是可选的。
    • 因为第一个路由仍然匹配
    【解决方案2】:

    如果您在 App_Start 中查找为您的 API 调用注册的路由,您会看到:

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

    您会注意到没有指定action。如果要映射到动作名称,可以将其更改为:

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

    但是你总是需要设置一个动作(除非它是默认的GET)。你不能再POST 直接连接控制器,你总是需要添加一个action

    根据this link,默认行为是查找以使用的 HTTP 方法开头的方法:

    为了找到动作,Web API 查看 HTTP 方法,然后查看 对于名称以该 HTTP 方法名称开头的操作。为了 例如,对于 GET 请求,Web API 会查找启动的操作 使用“Get...”,例如“GetContact”或“GetAllContacts”。这个 约定仅适用于 GET、POST、PUT 和 DELETE 方法。你可以 通过使用控制器上的属性来启用其他 HTTP 方法。 我们稍后会看到一个例子。

    另一种选择是为您的不同GET 调用创建不同的控制器,这是我过去所做的。

    【讨论】:

    • 我不确定我是否理解 action = "get" 的作用?我还更新了我的问题,包括了我的 webconfigs,但它仍然无法正常工作。我仍然可以在没有/create 的情况下进行 POST。
    • action = "get" 表示默认的{action} 参数是"get"。它试图复制 Web API 的原始行为。此外,如果您同时使用这两条路线,则没有操作的发布仍将遵循第一条路线。您需要将其删除。
    • 但是如果我删除第一个配置,那么我将如何通过 ID 获取用户?我希望能够通过当前有效的 id 和用户名获取用户。但是我明白了你的观点,它允许我在没有/create 的情况下发布,因为它遵循第一个路由配置。知道如何在不删除第一个配置或禁止我通过 id 获取用户的情况下进行设置吗?
    • 该示例默认允许您通过 ID 使用GET。除了GET,您还需要指定操作,例如POSTDELETE。这就是action = "get" 所做的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-08
    • 1970-01-01
    • 2021-04-29
    • 2015-02-28
    相关资源
    最近更新 更多