InputFormatters пуст в приложении стороны сервера Blazor (компоненты Razor) при использовании атрибута [FromBody] в контроллере - PullRequest
0 голосов
/ 10 февраля 2019

Я работаю над веб-игрой, использующей серверный блейзор (Razor Components) в превью Asp.Net Core 3.0.У меня есть класс контроллера, который я использую для сохранения игровых данных на сервере, но всякий раз, когда я делаю запрос на публикацию с допустимым телом JSON, контроллеру не удается отформатировать тело запроса, поскольку он не может найти какой-либо объект IInputFormatter из контекста.

Мне удалось выполнить простые запросы GET и POST без использования атрибута [FromBody], поэтому я знаю, что маршрутизация моего контроллера работает.Но всякий раз, когда я пытаюсь использовать методы HttpClient SendJsonAsync или PostJsonAsync и пытаюсь прочитать JSON с атрибутом [FromBody], я получаю следующую ошибку:

System.InvalidOperationException: 'Microsoft.AspNetCore.Mvc.MvcOptions.InputFormatters'не должно быть пустым.Для связывания с телом требуется по крайней мере один «Microsoft.AspNetCore.Mvc.Formatters.IInputFormatter».

Я также непосредственно установил Microsoft.AspNetCore.Mvc.Formatters.Json в свои проекты на всякий случай, но нетудачи.

Я регистрирую и добавляю mvc в свои службы в своем классе Server.Startup

// 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>();
    }

Мой класс контроллера и метод:

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 из контекста, но я не нашел никого другого с этой проблемой, и я не знаю, что попробовать дальше.Любая помощь будет оценена, спасибо

1 Ответ

0 голосов
/ 11 февраля 2019

Попробуйте: (следуйте этому порядку ...)

services.AddMvc().AddNewtonsoftJson();

services.AddRazorComponents<App.Startup>();
...