2

I have the following API Controller action

[HttpGet]
[Route("assets")]
public async Task<HttpResponseMessage> Get([FromUri]SearchCriteria searchCriteria)
{

}

When i test this with fiddler by accessing the url

http://localhost/assets

the searchCriteria parameter is null but when i try with

http://localhost/assets?param1=1&param2=2 then searchCriteria has got the instance of the object.

The SearchCriteria class is defined as

public class SearchCriteria
{
    public SearchCriteria()
    {
        Param1 = "";
        Param2 = "";
        PageIndex = 0;
        PageSize = 10;
    }
    public string Param1 { get; set; }
    public string Param2 { get; set; }
    public int PageIndex{ get; set; }
    public int PageSize { get; set; }
}

What is wrong in my approach? Why the action parameter is null when no querystring is passed?

Thanks

3 Answers 3

3

Well... because no data is present to create the parameter instance.

Look at the URLs. Here you have values for creating the parameter:

http://localhost/assets?param1=1&param2=2

Note how param1 and param2 are supplied with values, which map directly to the type of the parameter:

public string Param1 { get; set; }
public string Param2 { get; set; }

But in this URL, there are no values:

http://localhost/assets

So there's nothing to use to create the instance of the method parameter.

null literally means "there is nothing here". Since no parameter values were supplied, there is nothing there.

Sign up to request clarification or add additional context in comments.

4 Comments

But, i am having some default values in the object. So i would like to use the default. I have updated my query.
@MukilDeepthi: In order to achieve custom behavior in this case you'd probably need to create a custom model binder for your SearchCriteria type. There are a number of examples available online, and multiple ways to go about using it. (You can use it globally in the application, or just for this action method for example.)
Can i get some example please
For some reason the [FromUri] parameter is null only if I specify a custom [Route()]. Without the custom route and relying on the default routing to reach the controller by name, the parameter value is a new instance of the class.
0

If you are ok with search criteria been null, but want to avoid unit test errors, try

[HttpGet]
[Route("assets")]
public async Task<HttpResponseMessage> Get([FromUri]SearchCriteria searchCriteria)
{

if(searchCriteria == null)
    searchCriteria = new SearchCriteria();

}

Comments

0

Here's a custom attribute you can try. It delegates the work to the normal FromUriAttribute class and then simply instantiates the type if it's value is null

[AttributeUsage( AttributeTargets.Parameter )]
public sealed class FromUriOrNewAttribute : ParameterBindingAttribute
{
    public override HttpParameterBinding GetBinding( HttpParameterDescriptor parameter )
    {
        return new FromUriOrNewModelBinder( parameter );
    }

    private class FromUriOrNewModelBinder : HttpParameterBinding
    {
        public FromUriOrNewModelBinder( HttpParameterDescriptor descriptor ) : base( descriptor ) { }

        public override async Task ExecuteBindingAsync( ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken )
        {
            var binding = new FromUriAttribute( ).GetBinding( Descriptor );
            
            await binding.ExecuteBindingAsync( metadataProvider, actionContext, cancellationToken );

            SetValue( actionContext, actionContext.ActionArguments[ Descriptor.ParameterName ] ?? Activator.CreateInstance( Descriptor.ParameterType ) );
        }
    }
}

Usage example

[HttpGet]
[Route("assets")]
public async Task<HttpResponseMessage> Get([FromUriOrNew]SearchCriteria searchCriteria)
{

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.