1

I am using Postman to make a Get call. In the URL I have optional parameters with underscore in it. I want to assign those values to a class by using DataContract but I can't-do it. If I read them separately then there is no issue.

This is new to me so exploring what is the best approach to do it. Found some links where the suggestion is to go for an individual parameter but want to make sure I am not missing anything here.

Call: http://{{url}}/Host?host_name=Test&host_zipcode=123&host_id=123

Working: I can read these parameter values if I read them as an individual parameter.

[HttpGet]
[Route("api/Host")]
public async Task<HostResponse> GetHostInfo([FromUri (Name = "host_name")] string hostName, [FromUri (Name = "host_zipcode")] string hostZipCode, [FromUri(Name = "host_id")] string hostId)
{
}

Not Working: When I try to use class by using DataContract, I can't read it.

[HttpGet]
[Route("api/Host")]
public async Task<HostResponse> GetHostInfo([FromUri] HostInfo hostInfo)
{
}

[DataContract]
public class HostInfo
{
    [DataMember(Name = "host_name")]
    public string HostName { get; set; }

    [DataMember(Name = "host_zipcode")]
    public string HostZipCode { get; set; }

    [DataMember(Name = "host_id")]
    public string HostId { get; set; }
}

I also tried:

public class DeliveryManagerStatus
{
    [JsonProperty(PropertyName = "country")]
    public string Country { get; set; }

    [JsonProperty(PropertyName = "delivery_provider")]
    public string DeliveryProvider { get; set; }

    [JsonProperty(PropertyName = "job_id")]
    public string JobId { get; set; }
}

How can I assign these properties to a class?

2 Answers 2

2

You can use IModelBinder (details) implementation to parse it. Here is a DataMember based example (takes key names from DataMember attribute):

public class DataMemberBinder : IModelBinder
{
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        var props = bindingContext.ModelType.GetProperties();
        var result = Activator.CreateInstance(bindingContext.ModelType);
        foreach (var property in props)
        {
            try
            {
                var attributes = property.GetCustomAttributes(typeof(DataMemberAttribute), true);
                var key = attributes.Length > 0
                    ? ((DataMemberAttribute)attributes[0]).Name
                    : property.Name;
                if (bindingContext.ValueProvider.ContainsPrefix(key))
                {
                    var value = bindingContext.ValueProvider.GetValue(key).ConvertTo(property.PropertyType);
                    property.SetValue(result, value);
                }
            }
            catch
            {
                // log that property can't be set or throw an exception
            }
        }
        bindingContext.Model = result;
        return true;
    }
}

and usage

public async Task<HostResponse> GetHostInfo([FromUri(BinderType = typeof(DataMemberBinder))] HostInfo hostInfo)

In quick search I wasn't able to find any AttributeBased binder try and share if you will find it

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

1 Comment

IModelBinder not support in net 6 minimal api
0

Using your HostInfo class change your call to:

http://{{url}}/Host?hostInfo.host_name=Test&hostInfo.host_zipcode=123&hostInfo.host_id=123.

I would recommend changing your route to accept the complex type in the body if possible due to the limitations in query string length.

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.