Web API HttpClient PutAsync 返回 Http 404
Web API HttpClient PutAsync returning Http 404
我正在尝试将 PUT 发送到我的 Web API,但我对应该如何构建实际的 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-class
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 参数为空...
我通过在控制器中使用 FromBody 标记并将该参数包装在 http 请求正文中来使其工作。一个重要的注意事项是在参数前加上“=”号,以确保它被控制器正确解释。我还从路由配置中删除了相同的参数。最后,为了使客户端到服务器的请求正常工作,我不得不将 HttpServer Class 替换为 httpselfhostserver
我正在尝试将 PUT 发送到我的 Web API,但我对应该如何构建实际的 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-class
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 参数为空...
我通过在控制器中使用 FromBody 标记并将该参数包装在 http 请求正文中来使其工作。一个重要的注意事项是在参数前加上“=”号,以确保它被控制器正确解释。我还从路由配置中删除了相同的参数。最后,为了使客户端到服务器的请求正常工作,我不得不将 HttpServer Class 替换为 httpselfhostserver