Web API - 多个POST方法

3

我正在编写一个简单的Web API应用程序。我到了需要在Web API控制器中有两个POST方法的阶段。其中一个方法可以工作,而另一个方法则不行。我的路由表如下:

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

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

然后我定义我的方法如下:
    [HttpPost]
    public bool PostTaskAgain(My3TasksWebAPI.Data.Task task)
    {
        var oldTask = _db.Task.Where(t => t.Id == task.Id).SingleOrDefault();

        oldTask.DoAgain = true;
        oldTask.DateUpdated = task.DateUpdated;

        if (_db.SetOfTasks.Where(t => CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(t.DateCreated, CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday) == CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(DateTime.Now, CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday)).Any())
        {
            int currentSetOfTasksId = _db.SetOfTasks.OrderBy(s => s.DateCreated).FirstOrDefault().Id;

            My3TasksWebAPI.Data.Task newTask = new Data.Task() { CreatedBy = oldTask.CreatedBy, DateCreated = oldTask.DateCreated, DateUpdated = null, DoAgain = false, Notes = string.Empty, SetOfTasksId = currentSetOfTasksId, Status = false, Title = oldTask.Title, UserId = oldTask.UserId };

            _db.Task.Add(newTask);
        }

        _db.SaveChanges();

        return true;
    }

    // Post api/values/PostSetOfTasks/{setOfTasks}
    [HttpPost]
    public bool PostSetOfTasks(My3TasksWebAPI.Data.SetOfTasks setOfTasks)
    {
        _db.SetOfTasks.Add(setOfTasks);

        _db.SaveChanges();

        return true;
    }

当我尝试调用PostTaskAgain时,出现了内部服务器错误。我认为可能是路由表的问题,但我不确定如何处理两个POST方法。 我是这样从我的ASP.NET MVC应用程序调用Web API的:

HttpResponseMessage response = client.PostAsJsonAsync("api/values/PostSetOfTasks", model.SetOfTasks).Result;

并且

HttpResponseMessage response = client.PostAsJsonAsync("api/values/PostTaskAgain", taskToPost).Result;

这意味着我包括这些行动。

1
这两种方法可以合并成一个。接受多个项目的方法仍然可以接受单个项目。 - Paul Fleming
你是否在使用 Fiddler 来确定实际发布了什么内容? - Keith Nicholas
那个异常附带的错误消息是什么? - Brian Mains
你好,我看到问题了,这是一个非常愚蠢的问题。不知何故,Visual Studio没有警告我这个问题:{"$id":"1","Message":"An error has occurred.","ExceptionMessage":"LINQ to Entities does not recognize the method 'Int32 GetWeekOfYear(System.DateTime, System.Globalization.CalendarWeekRule, System.DayOfWeek)' method, and this method cannot be translated into a store expression.","ExceptionType":"System.NotSupportedException","StackTrace":" at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.DefaultTranslator.Translate(ExpressionConverter parent, MethodCall..... - Jakub Holovsky
你实际上在错误地使用Web API,你应该将方法定义为public bool POST,并让参数决定调用哪个方法,然后在路由中只需将其设置为api/{controller}。 - Tony
嘿,不是我使用不正确,而是我的linq查询出了问题,导致了这个问题。现在一切都好了。谢谢你的帮助。Jakub - Jakub Holovsky
2个回答

3
在webapi中使用POST可能会很棘手,但巧合的是,你的问题最终证明是微不足道的。然而,对于那些可能会遇到类似问题的人:
我将专门关注POST,因为处理GET是微不足道的。我不认为有很多人会搜索解决与webapi的GET相关的问题。无论如何...
如果你的问题是 - 在MVC Web Api中,如何: - 使用自定义操作方法名称而不是通用HTTP动词? - 执行多个POST请求? - 发布多个简单类型? - 通过jQuery发布复杂类型?
那么以下解决方案可能会有所帮助:
首先,在Web API中使用自定义操作方法,请添加一个Web API路由:
public static void Register(HttpConfiguration config)
{
            config.Routes.MapHttpRoute(
                name: "ActionApi",
                routeTemplate: "api/{controller}/{action}");
}

然后你可以创建像这样的操作方法:

[HttpPost]
        public string TestMethod([FromBody]string value)
        {
            return "Hello from http post web api controller: " + value;
        }

现在,从浏览器控制台运行以下 jQuery 代码:
$.ajax({
            type: 'POST',
            url: 'http://localhost:33649/api/TestApi/TestMethod',
            data: {'':'hello'},
            contentType: 'application/x-www-form-urlencoded',
            dataType: 'json',
success: function(data){ console.log(data) }
        });

其次,如果要执行多个帖子, 很简单,创建多个操作方法并用[HttpPost]属性进行装饰。 使用[ActionName("MyAction")]来分配自定义名称等。 下面第四点将介绍jQuery

第三, 首先,在单个操作中发布多个简单类型是不可能的,而且有一种特殊格式可以发布单个简单类型(除了在查询字符串或REST样式中传递参数)。 对于这一点,我曾经花费五个小时在Rest Clients上研究和搜索网站,最终以下链接帮助了我。我们还是引用内容,因为链接可能失效!

Content-Type: application/x-www-form-urlencoded
in the request header and add a = before the JSON statement:
={"Name":"Turbo Tina","Email":"na@Turbo.Tina"}

http://forums.asp.net/t/1883467.aspx?The+received+value+is+null+when+I+try+to+Post+to+my+Web+Api

无论如何,让我们跳过那个故事。接下来:

第四点,通过jQuery提交复杂类型,当然,$.ajax()将迅速发挥作用:

假设动作方法接受一个Person对象,该对象有一个id和一个name。因此,从javascript:

var person = { PersonId:1, Name:"James" }
$.ajax({
            type: 'POST',
            url: 'http://mydomain/api/TestApi/TestMethod',
            data: JSON.stringify(person),
            contentType: 'application/json; charset=utf-8',
            dataType: 'json',
            success: function(data){ console.log(data) }
        });

操作将如下所示:

[HttpPost]
        public string TestMethod(Person person)
        {
            return "Hello from http post web api controller: " + person.Name;
        }

以上所有内容对我来说都很有用!干杯!

你好,感谢回答,但我的代码本来就能正常工作。问题出在一个LINQ查询中,而不是Web API代码中。 - Jakub Holovsky

0

我的LINQ查询出现了问题。

The response from the server was: {"$id":"1","Message":"An error has occurred.","ExceptionMessage":"LINQ to Entities does not recognize the method 'Int32 GetWeekOfYear(System.DateTime, System.Globalization.CalendarWeekRule, System.DayOfWeek)' method, and this method cannot be translated into a store expression.","ExceptionType":"System.NotSupportedException","StackTrace":" at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.DefaultTransl‌​ator.Translate(ExpressionConverter parent, MethodCall....

在修正了linq查询之后,一切都正常工作了。Visual Studio并不介意我错误地执行linq查询。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接