Unable to fetch odata request parameter and values - asp.net-web-api

I have a webapi 2 project. I am making below calls to fetch parameter and values specified but RouteData is empty.
var routeData = HttpContext.Current.Request.RequestContext.RouteData;
var id = routeData.Values["contextId"] as string;
This is the url : http://localhost:29016/api/v1/Contexts(1)/Applications
and routing is setup like this,
// OData routing.
_configuration.MapODataServiceRoute(
"ODataRoute",
"api/v1/Contexts({contextId})",
GetModel(_configuration));
I need contextId parameter value before Controller action is called. I have verified that HttpContext.Current.Request.RequestContext refers to the correct request.

Related

Http PUT volley. Parameter in the middle of the url

I am using Volley for my HTTP requests and I have an HTTP put URL which looks like below.
http://mycompany.com/favorite/{roomNumber}/count. I am using a JSON object request. How do I make the API work with the extra "/count" in the API? I am passing the parameter room number in the JSON object.
JSON Object request works fine with this type of URL "http://mycompany.com/favorite/{roomNumber}"
JSON Object request
JsonObjectRequest request = new JsonObjectRequest(METHOD_TYPE_PUT, url, jsonObjectParams, responseListener, errorListener)
Can somebody help me with passing the JSON object parameter in the middle of the URL
Thanks.
You can call the API dynamically like this,
private void getTheApiData(int roomNumber){
JsonObjectRequest request = new JsonObjectRequest(METHOD_TYPE_PUT,
"mycompany.com/favorite" + roomNumber + "/count",
jsonObjectParams, responseListener, errorListener)
}
and call the above API dynamically by the method when you get the new data every time like this.
getTheAPiData(20) //if room number is 20
let me know if you have any issue #Shravani

web api support parameters while they don't have one

http://localhost:xxxx/api/BindAppointmentResources
works fine for me but when I'm trying to add any invalid object after controller (with this ? "http://localhost:xxxxx/api/BindAppointmentResources?Userid") in URL its gets the same result
I tried action-based routing , attribute routing so far but same result?
PS : I don't have parameters in WEB API
Route Config :
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
Query string parameters will automatically get bound to your parameters that have the same name in web api.
If no parameter names are found it will route the request to the base url (which is the url before the question mark).
So this url
http://localhost:xxxx/api/BindAppointmentResources?UserID=1
will, if no method with parameter name that match UserID are found, end up being routed to
http://localhost:xxxx/api/BindAppointmentResources
In the Get method you can still get the query string
var queryString = this.Request.GetQueryNameValuePairs();
To prevent binding parameters from query string and only allow bindings from route values, you could remove the default QueryStringValueProviderFactory from the default HttpConfiguration configuration. Read more about it in this article

Net Web API - How to pass a URL as input parameter on a Get

I am trying to pass a URL as a input parameter to a ApiController from an Angular REST call. The URL comes as a query string (this is a Provider Hosted app in SharePoint, I need the URL to query SP FWIW).
Here is the method signature in the ApiController:
// GET: api/ProjectSite/5
public IEnumerable<ProjectSite> Get(string id)
{
return ProjectSite.GetAllProjectSites(id);
}
And here is where I am making the call in Angular:
var spUrl = "'" + getParameterByName("SPHostUrl") + "'";
var queryUrl = "/api/ProjectSite/" + encodeURIComponent(spUrl);
return $http.get(queryUrl);
This generates a GET request that looks like this:
https://localhost:12345/api/ProjectSite/https%3A%2F%2Fcompany.sharepoint.com%2Fsites%2Fsite_dev%2Fweb
When I do I get 'HTTP 400 (Bad Request)' back. If I stop on a break point in the Angular code and change the input param to a simple string (e.g. 'asdf') the REST call is made and I see the Api is called. If I do not change the string and put a breakpoint inside the Get Api method the breakpoint is not reached, indicating that the code is blowing up somewhere in the route engine.
What I don't get is, while its encoded, the string I am trying to pass in should still be treated as a string, right? I also tried changing the input to Uri but that doesn't appear to work (and Uri isn't listed as a supported input type, anyways).
Anyone know how to pass a URL as input parameter?
Have you tried calling it using a query string?
var queryUrl = "/api/ProjectSite?id=" + encodeURIComponent(spUrl);

Pass URL containing a query string as a parameter ASP.Net Web API GET?

I'm trying to pass in an URL as a string parameter to a WEB API GET method.
The controller:
public class LinksController : ApiController
{
public HttpResponseMessage Get(string targetUrl)
{
//query db with targetURL
}
}
The aim is to query the database to see if the URL is stored. This works fine with simple URLs and URLs whose query string contains a single parameter, like:
http://www.youtube.com/watch?v=nLPE4vhSBx4
The problem I'm encountering is specifically when the query string contains multiple parameters, e.g.
http://www.youtube.com/watch?v=nLPE4vhSBx4&feature=youtube_gdata
When debugging, the value of targetUrl is only ".../watch?v=nLPE4vhSBx4" which means &feature=youtube_gdata is lost.
The GET request looks like this:
http://localhost:58056/api/links?targetUrl=http://www.youtube.com/watch? v=nLPE4vhSBx4&feature=youtube_gdata
I've also tried to add the following route in WebApiConfig.cs:
config.Routes.MapHttpRoute(
name: "Links",
routeTemplate: "api/links/{targetUrl}",
defaults: new { controller = "Links", targetUrl= RouteParameter.Optional }
);
But the GET request then results in 400 Bad Request.
So my question is, can't this be done? I would like the complete URL! Or would I need to change the method header to use the [FromBody] attribute and pass it as a JSON object?
You should URLEncode your target URL parameter so that it doesn't get mistaken for subsequent query string parameter. This means the URL you specified should appear as:
http://localhost:58056/api/links?targetUrl=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DnLPE4vhSBx4%26feature%3Dyoutube_gdata
And then inside your Get method, URLDecode the string that is passed as a parameter.
Both methods can be found in System.Web.HttpUtility

On Asp.net Web Api authorization filters, how can I access to parameters?

I'am starting with Asp.Net Web API and here's my problem :
I implement a custom authorization filter to inspect my message header looking for an API Key. Based on this API Key, I retrieve my user and then I would like to see if he can have access to some resources. The resources ID I want to check is on the parameters of the HTTP request. But when I'am on the AuthorizationFilter method, the actions parameters list is empty.
How can I do that ?
If I used an ActionFilter in replacement of an authorization filter, how can I be sure that this will be the first filter executed ? And globally, how can I specify the executing order of filters ?
Last question, is it possible to add some data "on the pipe" that I could retrieve on any filter ? Something like a session store but limited to the request ?
Thanks for any response
The authorization attributes run before parameter binding has run therefore you cannot (as you have seen) use the ActionArguments collection. Instead you will need to use the request uri for query parameters and route data for uri parameters as demonstrated below.
//request at http://localhost/api/foo/id?MyValue=1
public class MyAuthorizationAttribute : AuthorizeAttribute
{
protected override bool IsAuthorized(HttpActionContext actionContext)
{
//will not work as parameter binding has not yet run
object value;
actionContext.ActionArguments.TryGetValue("id", out value);
//Will get you the resource id assuming a default route like /api/foo/{id}
var routeData = actionContext.Request.GetRouteData();
var myId = routeData.Values["id"] as string;
//uri is still accessible so use this to get query params
var queryString = HttpUtility.ParseQueryString(actionContext.Request.RequestUri.Query);
var myQueryParam = queryString["MyValue"];
//and so on
}
}
About the execution order:
There are 3 different ways of specifying the execution order of filters using the FilterScope Enumeration... scope being Global, Controller and Action. The AuthoriseAttribute is "Global" and therefore it
Specifies an action before Controller.
If you needed to specify the execution order within these 3 scopes then you should read this blog article here where you will need to implement a FilterProvider
To add some data to the pipe:
Use the properties collection on the request this collection is available for the duration of the request.
protected override bool IsAuthorized(HttpActionContext actionContext)
{
actionContext.Request.Properties.Add("__MYKEY__","MyValue");
//access this later in the controller or other action filters using
var value = actionContext.Request.Properties["__MYKEY__"];
}
Another alternative to get to the parameters is to Execute the binding for the parameters.
try
{
var binding = actionContext.ActionDescriptor.ActionBinding;
var parameters = binding.ParameterBindings.OfType<ModelBinderParameterBinding>();
var newBinding = new HttpActionBinding(actionContext.ActionDescriptor, parameters.ToArray());
newBinding.ExecuteBindingAsync(actionContext, new CancellationToken());
var id = actionContext.ActionArguments["id"] as string;
}
catch
{
base.HandleUnauthorizedRequest(actionContext);
}
Note: You need to make sure you only filter on the parameters that will come from the Request URI, as I have noticed that executing the binding for any parameters that are expected to come from the Request body will no longer be passed on to the actual action. i.e. those parameters will be null.
This is just to note that you can do this, I'd recommend using GetRouteData()/RouteData as it is not likely to disrupt the further flow of ASP.NET MVC modelbinding.
var routeData = actionContext.ControllerContext.RouteData;
var id = routeData.Values["id"] as string;

Resources