Rest Web API HttpClient PutAsync返回Http 404

Rest Web API HttpClient PutAsync返回Http 404,rest,asp.net-web-api,asp.net-web-api2,dotnet-httpclient,Rest,Asp.net Web Api,Asp.net Web Api2,Dotnet Httpclient,我正试图向我的Web API发送一个PUT,但对于如何构造实际的Http请求,我有点纠结。下面是一个集成测试示例。使用HttpMessageInvoker调用Web API Put可以很好地工作,但我也希望在测试中使用HttpClient,因为这是我将在业务层中使用的 [TestMethod] public void Verify_UpdateBudgetData_Http_PUT() { int budgetId = 1; string

我正试图向我的Web API发送一个PUT,但对于如何构造实际的Http请求,我有点纠结。下面是一个集成测试示例。使用HttpMessageInvoker调用Web API Put可以很好地工作,但我也希望在测试中使用HttpClient,因为这是我将在业务层中使用的

    [TestMethod]
    public void Verify_UpdateBudgetData_Http_PUT()
    {
        int budgetId = 1;
        string appId = "DummyApp";
        string userId = "Dummy";
        string value = "400";
        string filterJSON =
                "{dimensionFilter:{\"Demo_Konto\":[\"3000\"],\"Demo_AO\":[\"200\"]},valueSpreadType:{\"Value1\":0}}";

        HttpConfiguration config = new HttpConfiguration();
        Konstrukt.SL.AggregationEngine.WebApiConfig.Register(config, new SL.AggregationEngine.AutofacStandardModule());
        HttpServer server = new HttpServer(config);

        /*this works*/
        using (HttpMessageInvoker client = new HttpMessageInvoker(server))
        {
            using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Put, 
                String.Format("http://localhost/AggregationEngine/UpdateBudgetData/{0}/{1}/{2}/{3}/{4}",
                budgetId, appId, userId, value, filterJSON)))
            using (HttpResponseMessage response = client.SendAsync(request, CancellationToken.None).Result)
            {
                Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, "Wrong http status returned");
            }
        };

        /*this does not work*/
        using (var client = new HttpClient())
        {
            //client.BaseAddress = new Uri("http://localhost");
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            var responseMessage =
                client.PutAsync(
                    String.Format("http://localhost/AggregationEngine/UpdateBudgetData/{0}/{1}/{2}/{3}/{4}",
                        budgetId, appId, userId, value, filterJSON), new StringContent("")).Result;
            Assert.AreEqual(HttpStatusCode.OK, responseMessage.StatusCode, "Wrong http status returned");
        }
    }
这是我的WebApiConfig课程

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config, Autofac.Module moduleToAppend)
    {
        config.Routes.MapHttpRoute(
            name: "UpdateBudgetData",
            routeTemplate: "AggregationEngine/{controller}/{budgetId}/{appId}/{userId}/{value}/{filterJSON}",
            defaults: new { filter = RouteParameter.Optional }
        );

        config.Routes.MapHttpRoute(
            name: "GetBudgetAndRefData",
            routeTemplate: "AggregationEngine/{controller}/{budgetId}/{userId}/{filterJSON}",
            defaults: new { filter = RouteParameter.Optional }
        );

        config.EnableCors();
        config.EnableSystemDiagnosticsTracing();

        // Autofac container
        // if not configured here you'll not have dependencies provided to your WebApiControllers when called
        var builder = new ContainerBuilder(); // yes, it is a different container here

        builder.RegisterAssemblyTypes( // register Web API Controllers
            Assembly.GetExecutingAssembly())
                .Where(t =>
                    !t.IsAbstract && typeof(ApiController).IsAssignableFrom(t))
                .InstancePerLifetimeScope();

        // register your graph - shared
        builder.RegisterModule(
            new AutofacStandardModule()); // same as with ASP.NET MVC Controllers

        if (moduleToAppend != null)
        {
            builder.RegisterModule(moduleToAppend);
        }

        var container = builder.Build();

        config.DependencyResolver = new AutofacWebApiDependencyResolver(
            container);
    }

    public static void Register(HttpConfiguration config)
    {
        Register(config, null);
    }
}

如何修复对PutAsync的HttpClient调用?我应该在主体中嵌入FilterJSON参数吗?如果是,如何做到这一点?我已经尝试过了,但是FromBody参数为null…

我通过在控制器中使用FromBody标记,然后将该参数包装到http请求主体中,使其正常工作。需要注意的一个重要事项是在参数前面加上“=”号,以确保控制器正确解释了该参数。我还从路由配置中删除了相同的参数。最后,为了使客户机到服务器的请求能够工作,我必须用httpselfhostserver替换HttpServer类