Here is a screenshot of my postman screen where I am attempting to make a get request to a web api call.
I also tried to make the call using [] with no numbers for each parameter and this did not work either. In both cases, the filenames array of string ended up being null. Disregard the error at the bottom of the screen as I replaced the actual api call with a sample. I saw the null value when I hit the breakpoint for the correct api call. Am I missing something here?
Given your action:
public async Task<IHttpActionResult> Test(string[] filenames) {
// ...
}
You need to add a [FromUri] attribute to your string[] filenames parameter. The reason is documented here:
By default, Web API uses the following rules to bind parameters:
If the parameter is a "simple" type, Web API tries to get the value from the URI. Simple types include the .NET primitive types (int, bool, double, and so forth), plus TimeSpan, DateTime, Guid, decimal, and string, plus any type with a type converter that can convert from a string. (More about type converters later.)
For complex types, Web API tries to read the value from the message body, using a media-type formatter.
Arrays are considered a complex type. The [FromUri] attribute will override the default behaviour and instruct Web API to try and bind this parameter from the URI.
Related
I've a Custom Attribute which I'm using to authorize the request before it hits the Controller Action, in ASP.NET Core Web API. In the image below, "SecureMethod" is the custom attribute.
I want to add a property in the Custom Attribute, which I want to bind to one of the Route Values, please refer to the image below:
I want to bind "userIDs" route-value to one of the Custom Attribute's property ("UserIDs", this is an example attribute).
Is there any way I can bind the route-value to a custom-attribute's property?
TIA
One way you can do this is by passing the name of the route parameter to the attribute, and examining the route data in the attribute itself. For example:
[SecureMethod(PermissionRequired = AccessPermissionEnum.DeleteUsers, UserIdsKey = "userIds")]
Then something like:
public AccessPermissionEnum PermissionRequired { get; set; }
public string UserIdsKey { get; set; }
public override void OnActionExecuting(ActionExecutingContext context)
{
// Depending on how you pass your userIds to the action, you
// may need to use something else from context to get the data,
// but it's all available in there.
var userIds = context.ActionArguments[UserIdsKey];
// Do something with the ids.
base.OnActionExecuting(context);
}
Whilst this works, and in certain places it works really well, you should be aware that the filter now has intimate knowledge of the parameter being passed in. For the most part, this usually doesn't matter so much, but it's an approach you shouldn't use everywhere because it will end up adding a lot of coupling if not used well. It's a useful tool to use every now and then.
No, it is not possible.
Attribute parameters are restricted to constant values of the following types:
Simple types (bool, byte, char, short, int, long, float, and double)
string
System.Type
enums
object (The argument to an attribute parameter of type object must be
a constant value of one of the above types.)
One-dimensional arrays of any of the above types
You cannot nest attributes and you cannot pass non-constant values to attribute parameter. Even though you can declare an attribute parameter as type object, the actual argument you pass in must still be a constant string, bool, etc (declaring it as an object just means you can use any of these types each time you declare the attribute).
I'm using:
return RedirectToAction("GetSchedule", new { requirements = preCheckParams.Requirements, weightValues = preCheckParams.WeightValues});
in my aspnetcore app. Next I want to reuse the values I pass to the anonymous object in another action:
public IActionResult GetSchedule(List<string> requirements, Dictionary<string, int> weightValues)
Strangely, the first value gets bound to the List in GetSchedule action, yet the second object, which is a dictionary, is empty. Are there any special rules regarding dictionaries in such cases?
You can't pass classes in the routeValues parameter of RedirectToAction.
RedirectToAction method return value is HTTP 302 (Status302Found) which produces a GET request to the specified action. Which means that all your parameters will be put in URL as query string.
List/Array of strings requirements can be passed in URL since it binds to ?requirements=value1&requirements=value2&.. etc in query string, but anything more complex than that cannot be bound, only primitive values.
You have several options that first come to my mind:
Serialize object to JSON and pass it as a string. This will result in ugly and confusing URL, but it's least painful way.
Use temporary storage if you don't require strictly stateless mechanism. Store before the action and retrieve the dictionary when you enter it.
If you can retrieve weight values from the backend, you may pass some identifier to query by it.
I am using ASP.NET Core to host a Web API. I have the following action defined in my Orders controller:
[HttpGet("list")]
public List<Order> List([FromQuery] int index = 0, [FromQuery] int length = 100)
{
return GetOrders(index, length);
}
The following returns a single order:
https://localhost:5000/api/v1/Orders/list?index=0&length=1
The following returns 100 orders:
https://localhost:5000/api/v1/Orders/list?index=0&length=a
It appears that for a request, any parameters that cannot be converted to the declared type will be treated as missing, thus resulting in the use of the default value as per the example above, or the value type default value, or null for reference types.
In this case it is preferable to have the request fail when executed with mismatched parameter types rather than have it proceed with default/null values.
Is there a way to modify this behaviour?
This link is a comprehensive description of how model binding works in web api:
https://learn.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api
Based on it, I'd say you'll need a custom model binder that throws an exception when it cannot convert the value.
I am building a webapi to getBalance of a customer from Db.It works well and i can retrieve the data.But the problem is in the parameter part.
For eg. In ASP.NET webservice when we request the service it gives us a page where according to the the service we get to enter the parameters in the textbox and upon
firing up the service we get the data.
I have my webapi up and running and the uri looks like this --- http://localhost/api/accounts/balance/cs-001
AccountsController
public class AccountsController : ApiController
{
[HttpGet]
[ActionName("balance")]
public string Getbalance(string accountNumber)
{
var data = BusinessLayer.Api.AccountHolderApi.GetBalance(accountNumber);
return data;
}
}
And my route
RouteTable.Routes.MapHttpRoute("OfficeApi", "api/{controller}/{action}/{accountNumber}");
So the accountNumber is the paramater here.Now one of my mobile app dev friend to is going to use this api suggests me to move account number in parameter rather than url.Like in my case we append the parameter in the url to retrieve the balance from the db.I want to know how to move the account number (the param) from the url to parameter in asp.net webapi.
I am new to webapi.Help needed.Thank You.
All you have to do is change the route since account number is already a parameter on the function:
RouteTable.Routes.MapHttpRoute("OfficeApi", "api/{controller}/{action}");
Then you'll be able to do:
http://localhost/api/accounts/balance?accountNumber=cs-001
#Avitus's answer is correct. Here is some belabor in case you are interested.
If someone requests this URL: http://localhost/api/accounts/balance?accountNumber=cs-001
ASP.NET routing will figure out the controller and action based on your routing configuration. Once the controller and action have been discovered, then it will try to bind the parameters in the action like this:
By default, Web API uses the following rules to bind parameters:
If the parameter is a "simple" type, Web API tries to get the value from the URI. Simple types include the .NET primitive types (int, bool, double, and so forth), plus TimeSpan, DateTime, Guid, decimal, and string, plus any type with a type converter that can convert from a string. (More about type converters later.)
For complex types, Web API tries to read the value from the message body, using a media-type formatter.
Here is the full article.
I received a WSDL from a customer and created a proxy class that I can use in .NET. The WSDL contains one call with a large number of parameters.
In my code, I collect data from entities in Microsoft CRM. Some of the fields in the entities are mandatory and others are not. The result is that I can retrieve an entity with missing (non-mandatory) fields that I have to send through the SOAP interface.
The generated proxy class contains the signature of the method with the large number of parameters. When I call the method with a reference type parameter that is "null", it works just fine. Sometimes a value type parameter is "null" (not returned in the entity). I can't call the generated method in the proxy class because the (value type) parameters of the method in the proxy are not nullable.
Is it possible to use nullable types (bool?, long?) on the .NET side that will result in '< s:element minOccurs="0"' attributes on the SOAP side?
My problem is not solved with the answer from this question: Can I have an optional parameter for an ASP.NET SOAP web service
That question relates to one optional parameter. That can be solved with overloads. In my case, the signature has more than 30 parameters and 7 of them are value types that sometimes have no value. If I implement that with overloads, I need 128 overloaded methods to match all combinations.
I tried to make the parameters optional in the proxy class:
long accountCountry,
[System.Xml.Serialization.XmlElementAttribute(IsNullable = true)]long? accountLegalForm,
string accountName,
This resulted in an System.InvalidOperationException "Method xxx can not be reflected." with an inner exception "There was an error reflecting 'accountLegalForm'."