在控制器中使用 [FromBody] 属性时,Blazor 服务器端应用程序(Razor 组件)中的 InputFormatters 为空
InputFormatters is empty in Blazor Server side Side app (Razor Components) when using [FromBody] attribute in controller
我正在 Asp.Net Core 3.0 预览版中使用服务器端 blazor(Razor 组件)开发网页游戏。我有一个控制器 class 用于将游戏数据保存到服务器,但是每当我使用有效的 JSON 主体发出 post 请求时,控制器无法格式化请求正文,因为它无法从上下文中找到任何 IInputFormatter。
我已经能够在不使用 [FromBody] 属性的情况下执行简单的 GET 请求和 POST,所以我知道我的控制器路由正在工作。但是每当我尝试使用 HttpClient SendJsonAsync 或 PostJsonAsync 方法并尝试使用 [FromBody] 属性读取 JSON 时,我都会收到以下错误:
System.InvalidOperationException: 'Microsoft.AspNetCore.Mvc.MvcOptions.InputFormatters'不能为空。
至少需要一个 'Microsoft.AspNetCore.Mvc.Formatters.IInputFormatter' 才能从正文中绑定。
我也直接安装了Microsoft.AspNetCore.Mvc.Formatters.Json到我的项目中,只是inn case,但运气不好。
我在 Server.Startup class
中注册并向我的服务添加了 mvc
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorComponents<App.Startup>();
services.AddMvc();
//Register httpclient service
if (!services.Any(x => x.ServiceType == typeof(HttpClient)))
{
// Setup HttpClient for server side in a client side compatible fashion
services.AddScoped<HttpClient>(s =>
{
// Creating the URI helper needs to wait until the JS Runtime is initialized, so defer it.
var uriHelper = s.GetRequiredService<IUriHelper>();
return new HttpClient
{
BaseAddress = new Uri(uriHelper.GetBaseUri())
};
});
}
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc(routes => { routes.MapRoute(name: "default", template: "{controller}/{action}"); });
app.UseRazorComponents<App.Startup>();
}
我的控制器class和方法:
public class GameController : Controller
{
[HttpPost]
[Route("api/Game/SaveGame")]
public string SaveGame([FromBody]GameInfoBody gameInfo)
{
//save the game to database
}
}
我的客户在我的 Game.cshtml 页面中致电:
public async Task<string> SaveGameToDatabase(GameEngine game)
{
var request = new GameInfoPostModel()
{
gameInfo = new GameInfoBody
{
ID = game.ID,
GameEngine = game,
Players = game.Teams.SelectMany(x => x.Players).Select(x => new PlayerGameMapping() { PlayerID = x.ID }).ToList()
}
};
try
{
var result = await Client.SendJsonAsync<string>(HttpMethod.Post, "/api/Game/SaveGame", request);
return result;
}
catch (Exception e)
{
return "Failed to save" + e.Message;
}
}
完整堆栈跟踪:
System.InvalidOperationException: 'Microsoft.AspNetCore.Mvc.MvcOptions.InputFormatters' must not be empty. At least one 'Microsoft.AspNetCore.Mvc.Formatters.IInputFormatter' is required to bind from the body.
at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinderProvider.GetBinder(ModelBinderProviderContext context)
at Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderFactory.CreateBinderCoreUncached(DefaultModelBinderProviderContext providerContext, Object token)
at Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderFactory.CreateBinder(ModelBinderFactoryContext context)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.GetParameterBindingInfo(IModelBinderFactory modelBinderFactory, IModelMetadataProvider modelMetadataProvider, ControllerActionDescriptor actionDescriptor, MvcOptions mvcOptions)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.CreateBinderDelegate(ParameterBinder parameterBinder, IModelBinderFactory modelBinderFactory, IModelMetadataProvider modelMetadataProvider, ControllerActionDescriptor actionDescriptor, MvcOptions mvcOptions)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvokerCache.GetCachedResult(ControllerContext controllerContext)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvokerProvider.OnProvidersExecuting(ActionInvokerProviderContext context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionInvokerFactory.CreateInvoker(ActionContext actionContext)
at Microsoft.AspNetCore.Mvc.Routing.MvcEndpointDataSource.<>c__DisplayClass22_0.<CreateEndpoint>b__0(HttpContext context)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
阅读文档告诉我默认包含 JsonFormatters。我已使用 Fiddler 验证我的调用具有正确的内容类型和有效 JSON。我在想,如果它从上下文中找不到任何 InputFormatters,我一定没有正确配置服务,但我还没有发现其他人有这个问题,我不知道下一步该尝试什么。任何帮助将不胜感激,谢谢
试试这个:
(按照这个顺序...)
services.AddMvc().AddNewtonsoftJson();
services.AddRazorComponents<App.Startup>();
我正在 Asp.Net Core 3.0 预览版中使用服务器端 blazor(Razor 组件)开发网页游戏。我有一个控制器 class 用于将游戏数据保存到服务器,但是每当我使用有效的 JSON 主体发出 post 请求时,控制器无法格式化请求正文,因为它无法从上下文中找到任何 IInputFormatter。
我已经能够在不使用 [FromBody] 属性的情况下执行简单的 GET 请求和 POST,所以我知道我的控制器路由正在工作。但是每当我尝试使用 HttpClient SendJsonAsync 或 PostJsonAsync 方法并尝试使用 [FromBody] 属性读取 JSON 时,我都会收到以下错误:
System.InvalidOperationException: 'Microsoft.AspNetCore.Mvc.MvcOptions.InputFormatters'不能为空。 至少需要一个 'Microsoft.AspNetCore.Mvc.Formatters.IInputFormatter' 才能从正文中绑定。
我也直接安装了Microsoft.AspNetCore.Mvc.Formatters.Json到我的项目中,只是inn case,但运气不好。
我在 Server.Startup class
中注册并向我的服务添加了 mvc// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorComponents<App.Startup>();
services.AddMvc();
//Register httpclient service
if (!services.Any(x => x.ServiceType == typeof(HttpClient)))
{
// Setup HttpClient for server side in a client side compatible fashion
services.AddScoped<HttpClient>(s =>
{
// Creating the URI helper needs to wait until the JS Runtime is initialized, so defer it.
var uriHelper = s.GetRequiredService<IUriHelper>();
return new HttpClient
{
BaseAddress = new Uri(uriHelper.GetBaseUri())
};
});
}
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc(routes => { routes.MapRoute(name: "default", template: "{controller}/{action}"); });
app.UseRazorComponents<App.Startup>();
}
我的控制器class和方法:
public class GameController : Controller
{
[HttpPost]
[Route("api/Game/SaveGame")]
public string SaveGame([FromBody]GameInfoBody gameInfo)
{
//save the game to database
}
}
我的客户在我的 Game.cshtml 页面中致电:
public async Task<string> SaveGameToDatabase(GameEngine game)
{
var request = new GameInfoPostModel()
{
gameInfo = new GameInfoBody
{
ID = game.ID,
GameEngine = game,
Players = game.Teams.SelectMany(x => x.Players).Select(x => new PlayerGameMapping() { PlayerID = x.ID }).ToList()
}
};
try
{
var result = await Client.SendJsonAsync<string>(HttpMethod.Post, "/api/Game/SaveGame", request);
return result;
}
catch (Exception e)
{
return "Failed to save" + e.Message;
}
}
完整堆栈跟踪:
System.InvalidOperationException: 'Microsoft.AspNetCore.Mvc.MvcOptions.InputFormatters' must not be empty. At least one 'Microsoft.AspNetCore.Mvc.Formatters.IInputFormatter' is required to bind from the body.
at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinderProvider.GetBinder(ModelBinderProviderContext context)
at Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderFactory.CreateBinderCoreUncached(DefaultModelBinderProviderContext providerContext, Object token)
at Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderFactory.CreateBinder(ModelBinderFactoryContext context)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.GetParameterBindingInfo(IModelBinderFactory modelBinderFactory, IModelMetadataProvider modelMetadataProvider, ControllerActionDescriptor actionDescriptor, MvcOptions mvcOptions)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.CreateBinderDelegate(ParameterBinder parameterBinder, IModelBinderFactory modelBinderFactory, IModelMetadataProvider modelMetadataProvider, ControllerActionDescriptor actionDescriptor, MvcOptions mvcOptions)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvokerCache.GetCachedResult(ControllerContext controllerContext)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvokerProvider.OnProvidersExecuting(ActionInvokerProviderContext context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionInvokerFactory.CreateInvoker(ActionContext actionContext)
at Microsoft.AspNetCore.Mvc.Routing.MvcEndpointDataSource.<>c__DisplayClass22_0.<CreateEndpoint>b__0(HttpContext context)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
阅读文档告诉我默认包含 JsonFormatters。我已使用 Fiddler 验证我的调用具有正确的内容类型和有效 JSON。我在想,如果它从上下文中找不到任何 InputFormatters,我一定没有正确配置服务,但我还没有发现其他人有这个问题,我不知道下一步该尝试什么。任何帮助将不胜感激,谢谢
试试这个: (按照这个顺序...)
services.AddMvc().AddNewtonsoftJson();
services.AddRazorComponents<App.Startup>();