William
William

Reputation: 1395

MVC optional body parameter

I am trying to wire up a webhook from a 3rd party system.

When creating the subscription it hits the URL i provide and requires a validated token returned to create the hook.

When the event is triggered the hook posts to the same URL i provided with data in the body.

How can I get a Core 2.1 MVC controller/routing to see these as either two different methods on the controller or a method signature where the complex object is optional?

Either two POST methods (this creates ambiguity exception)

public async Task<IActionResult> Index(){}
public async Task<IActionResult> Index([FromBody] ComplexObject co){}

or complexObject is optional (if not it throws a Executing ObjectResult, writing value of type '"Microsoft.AspNetCore.Mvc.SerializableError" on the subscription creation step.)

public async Task<IActionResult> Index([FromBody] ComplexObject co){}

Upvotes: 5

Views: 2633

Answers (2)

rrreee
rrreee

Reputation: 893

Another way around this :

public class AllowBindToNullAttribute : ModelBinderAttribute
{
    public AllowBindToNullAttribute()
        : base(typeof(AllowBindToNullBinder))
    {

    }

    public class AllowBindToNullBinder : IModelBinder
    {
        public async Task BindModelAsync(ModelBindingContext bindingContext)
        {
            var stream = bindingContext.HttpContext.Request.Body;
            string body;
            using (var reader = new StreamReader(stream))
            {
                body = await reader.ReadToEndAsync();
            }

            var instance = JsonConvert.DeserializeObject(body, bindingContext.ModelType);
            bindingContext.Result = ModelBindingResult.Success(instance);
        }
    }
}

You'd use it like this:

public async Task<IActionResult> Index(
    [FromBody] [AllowBindToNull] ComplexObject co = null){}

Upvotes: 2

William
William

Reputation: 1395

I used the empty parameter method signature and checked the body for data. Not ideal.

Upvotes: 0

Related Questions