Nathan Thomas
Nathan Thomas

Reputation: 43

How do I pass an custom object from an async action filter to a controller in ASP.net core?

I haven't been able to find a good answer to this problem or whether it is even possible. I want to make it so that my filter will add an object as a parameter using the context.ActionArguments["personService"] = personService. I am able to make an argument using a string type, but when I try to use a custom object I keep getting a 415 error using postman.

I know that I can pass an object using the context.HttpContext.Items.Add("personService",personService), but it is not an elegant solution for what I am doing. I have a class which is as follows:

public class PersonService
    {
        private readonly string _name;
        private readonly int _age;
        private readonly string _location;
        public Person(string name, int age, string location)
        {
            _name = name;
            _age = age;
            _location = location;
        }

        public string printPerson(){
            return "name: {0} age: {1} location {2}", _name, _age, _location";
        }
    }

Then my filter looks like the following:

public class PersonFilterAttribute: Attribute, IAsyncActionFilter
    {
        public PersonFilterAttribute()
        {
        }

        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
           context.ActionArguments["personService"] = new PersonService("Thomas", 29,"Miami");

          
          await next();
        }
    }
 [HttpGet("personService")]
 [ServiceFilter(typeof(PersonFilterAttribute))]
 public async Task<string> passTheObject(Person person)
    {
          return person.printPerson();
    }

Upvotes: 4

Views: 922

Answers (1)

Shah
Shah

Reputation: 1399

You have to make couple of changes to work. First, change the API to add the attribute [FromQuery] to specify the source for your complex type parameter (By default Route data and query string values are used only for simple types).

[HttpGet("personService")]
[ServiceFilter(typeof(PersonFilterAttribute))]
public async Task<string> passTheObject([FromQuery] Person person)
{
    return person.printPerson();
}

And next you have to add the parameter less constructor to the Model Person:

public class Person {
    private readonly string _name;
    private readonly int _age;
    private readonly string _location;

    public Person() {
    }

    public Person(string name, int age, string location) {
        _name = name;
        _age = age;
        _location = location;
    }

    public string printPerson() {
        return string.Format("name: {0} age: {1} location {2}", _name, _age, _location);
    }
}

Since before executing OnActionExecution Action filter, Model Binding is already done and default constructor is needed to create instance of the model.

Upvotes: 1

Related Questions