JDBennett
JDBennett

Reputation: 1505

.NET Core OData Action Parameter Null

My Odata Action Parameters are not resolving / deserializing.

I am using dotnet core 2.2 to surface an OData controller.

I need to implement an unbounded action. The action parameter (UserDto userDto) is not being deserialized by the OData routing engine:

    [AllowAnonymous]
    [HttpPost]
    [ODataRoute(Routing.Endpoints.UserRoutes.AUTHENTICATE)]
    public async Task<IActionResult> Authenticate(UserDto userDto)
    {
        var user = await _userService.Authenticate(userDto?.Username, userDto?.Password);

        if (user == null)
            return BadRequest("Username or password is incorrect");

        var dto = Mapper.Map<UserDto>(user);

        return Ok(dto);
    }

Here is my configuration:

         app.UseMvc(routeBuilder =>
        {
            var odataBuilder = new ODataConventionModelBuilder(app.ApplicationServices);
            odataBuilder.EnableLowerCamelCase();

            odataBuilder.EntitySet<BookDto>(nameof(Book));
            odataBuilder.EntitySet<UserDto>(nameof(User));

            var authenticate = odataBuilder.Action(Routing.Endpoints.UserRoutes.AUTHENTICATE);
            authenticate.Parameter<UserDto>("userDto");

            routeBuilder.Select().Expand().Filter().OrderBy().Count().MaxTop(int.MaxValue);
            routeBuilder.MapODataServiceRoute("odata", string.Empty, odataBuilder.GetEdmModel());
        });

Here is the UserDto:

   public class UserDto
   {
       [Key] public Guid Id { get; set; }

       public string Username { get; set; }
       public string Password { get; set; }
       public string Token { get; set; }
   }

When I post:

enter image description here

The action is resolved by the routing engine - but the parameter does not have the "Username" and "Password" values:

enter image description here

If I use the [FromBody] attribute on the parameter - the "userDto" parameter is null:

enter image description here

The schema seems correct:

<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Default">
    <Action Name="authenticate">
         <Parameter Name="userDto" Type="ExampleApi.Dto.UserDto"/>
    </Action>
    <EntityContainer Name="Container">
         <EntitySet Name="Book" EntityType="ExampleApi.Dto.BookDto"/>
         <EntitySet Name="User" EntityType="ExampleApi.Dto.UserDto"/>
          <ActionImport Name="authenticate" Action="Default.authenticate"/>
    </EntityContainer>
 </Schema>

I have tried following this: Action Parameter Support

And even Microsofts version (albeit dated): Actions and Functions in OData

Been banging my head on this all day...

Upvotes: 0

Views: 537

Answers (1)

pagratios
pagratios

Reputation: 394

You could use simple WebApi attributes only to achieve authentication

 public class UserController : ODataController
 {
    [AllowAnonymous]
    [HttpPost("user/auth")]
    public async Task<IActionResult> Authenticate([FromBody] UserDto userDto)
    {
        return Ok(userDto);
    }
 }

Upvotes: 3

Related Questions