Asp.net mvc6 app从web api接收null参数

时间:2017-01-17 21:37:27

标签: c# asp.net-mvc asp.net-core-mvc

我的控制器应该在使用api时从调用者接收某个对象,但在我的情况下,它接收我请求的类型的对象,但是属性设置为null。参数有[FromBody]礼仪,但我也是试过[FromForm]并彻底消除礼仪,但结果几乎相同,当我使用[FromBody]时我的应用程序抛出Null异常,当我尝试从对象访问某个字段时,在其他情况下,这些属性只是设置为默认值(如果它是一个int是0而一个字符串是“”)。如果它有帮助..我从一个招摇的生成页面调用api。

这是我的目标:

using AT.Core.Cqrs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace DotnetProject.BusinessLayer.Implementation.Queries
{
    public class GetTestByIdQuery : IQuery
    {
        public int TestId { get; set; }
    }
}

来自控制器的http终点:

 [HttpGet]
    [Route("getTest")]
    public int GetTest([FromServices]GetTestByIdQueryHandler handler,[FromBody]GetTestByIdQuery query)
    {
        return query.TestId;   
    }

我的ConfigureServices函数来自启动:

  public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy",
                builder => builder.AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials());
        });




        // Add framework services.
        services.AddApplicationInsightsTelemetry(Configuration);
        services.AddScoped<IUserService, UserService>();
        services.AddScoped<IUserRepository, UserRepository>();
        services.AddScoped<ITestRepository, TestRepository>();
        services.AddScoped<ITestService, TestService>();
        services.AddScoped<IRoleService, RoleService>();
        services.AddScoped<IRoleRepository, RoleRepository>();
        services.AddScoped<ICommandHandler<DeleteUserCommand>, DeleteUserHandler>();
        services.AddScoped<ICommandHandler<UpdateUserCommand>,UpdateUserHandler>();
        services.AddScoped<ICommandHandler<AddUserCommand>, AddUserHandler>();
        services.AddScoped<ICommandHandler<DeleteTestCommand>, DeleteTestHandler>();
        services.AddScoped<ICommandHandler<UpdateTestCommand>, UpdateTestHandler>();
        services.AddScoped<ICommandHandler<AddTestCommand>, AddTestHandler>();
        services.AddScoped<IQueryHandler<GetAllTestsQuery,GetAllTestsQueryResult>,GetAllTestsQueryHandler>();
        services.AddScoped<IQueryHandler<GetTestByIdQuery, GetTestByIdQueryResult>,GetTestByIdQueryHandler>();
        services.AddScoped<IQueryHandler<GetAllUsersQuery, GetAllUsersQueryResult>, GetAllUsersQueryHandler>();
        services.AddScoped<IQueryHandler<GetUserByIdQuery, GetUserByIdQueryResult>, GetUserByIdQueryHandler>();
        services.AddScoped<GetAllTestsQueryHandler, GetAllTestsQueryHandler >();
        services.AddScoped<GetTestByIdQueryHandler, GetTestByIdQueryHandler>();
        services.AddScoped<GetAllUsersQueryHandler, GetAllUsersQueryHandler>();
        services.AddScoped <GetUserByIdQueryHandler, GetUserByIdQueryHandler> ();
        services.AddScoped <AddTestHandler, AddTestHandler> ();
        services.AddScoped <AddUserHandler, AddUserHandler> ();
        services.AddScoped <DeleteTestHandler, DeleteTestHandler> ();
        services.AddScoped <DeleteUserHandler, DeleteUserHandler> ();
        services.AddScoped <UpdateTestHandler, UpdateTestHandler> ();
        services.AddScoped <UpdateUserHandler, UpdateUserHandler> ();

        services.AddDbContext<ApplicationContext>();
        services.AddMvc(config =>
        {
            var policy = new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .Build();
            config.Filters.Add(new AuthorizeFilter(policy));
            config.OutputFormatters.Clear();
            config.OutputFormatters.Add(new JsonOutputFormatter(new JsonSerializerSettings()
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
            }, ArrayPool<char>.Shared));
        });

        services
    .AddMvc()
    .AddJsonOptions(jsonOptions =>
    {
        jsonOptions.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
    });
        // Inject an implementation of ISwaggerProvider with defaulted settings applied
        services.AddSwaggerGen();
    }

编辑:当我使用[FromBody]礼仪时,标题+正文。

Curl
curl -X GET --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ \ 
   "testId": 60 \ 
 }' 'http://localhost:5000/api/Test/getTest'
Request URL
http://localhost:5000/api/Test/getTest
Response Body
no content
Response Code
0
Response Headers
{
  "error": "no response from server"

当我没有礼仪时,标题+身体:

Curl
curl -X GET --header 'Accept: application/json' 'http://localhost:5000/api/Test/getTest'
Request URL
http://localhost:5000/api/Test/getTest
Response Body
0
Response Code
200
Response Headers
{
  "date": "Tue, 17 Jan 2017 22:49:14 GMT",
  "transfer-encoding": "chunked",
  "content-type": "application/json; charset=utf-8",
  "server": "Kestrel",
  "": ""
}

1 个答案:

答案 0 :(得分:0)

我打赌在行动方法中混合[FromBody]和[FromServices]是失败的。 [FromServices]是一种构造,用于启用控制反转,以将服务实例注入控制器。严格地说,从IOC背景来看,将值注入动作方法通常是一个坏主意,所以我很惊讶地看到这个功能甚至存在。

要使其正常工作,请将[FromServices]参数移动到控制器的构造函数中,然后在操作方法中,您可以访问此服务以获取所需的值。

public class MySimpleController
{
    private GetTestByIdQueryHandler _handler;
    public MySimpleController([FromServices] GetTestByIdQueryHandler handler)
    {
        _handler = handler
    }

    [HttpGet]
    [Route("getTest")]
    public int GetTest([FromBody]GetTestByIdQuery query)
    {
        return _handler.SomeMethod(query.TestId);   
    }
}