How to obtain request parameter from query string or request body inside ASP.NET Web API 2 Controller - asp.net

In PHP, one can access request property by using the $_REQUEST 'superglobal' variable.
In Java Servlet, one can also do something similar by calling getParameter(string) or getParameterValues(string) on the incoming HttpServletRequest instance.
Both of these method do not care if the data is conveyed on the query string or on the body. They are HTTP-method-agnostic-ways of getting request properties.
How to do the same using ASP.NET 4.x (not Core) Web API 2?
As far as possible, I do not want to use model binding or route parameter. I just want to use built in Properties of the ApiController to access the request parameter directly.
Here's what I'm trying to do:
public class MyController : ApiController
{
[HttpPost]
public IHttpActionResult Index()
{
// somehow obtain 'requestParam ' either from query string OR from request body
var requestParam = Request.???
return Ok(requestParam);
}
}

Related

ASP.Net MVC Controller accepting "application/x-www-form-urlencoded" content type

I inherited an old ASP.Net MVC web application. I need to modify it and add a page that can handle an incoming HTTP POST with hidden fields sent as "application/x-www-form-urlencoded" content type. This page's URL will be provided as a webhook URL to an external system that will use it to send back the control to my application and will provide some data in the form of "application/x-www-form-urlencoded" content type.
As I mentioned, this is an old MVC 5 application and is not targeting the .NET Core framework. Therefore I cannot declare my controller's method like this:
[HttpPost]
[Consumes("application/x-www-form-urlencoded")]
public void Webhook([FromForm] Response webHookResponse)]
The "Consumes" and "FromForm" attributes are available in the "Microsoft.AspNetCore.Mvc" namespace, but I don't have access to that in my application. Is there a different way to handle this in MVC 5?
Thanks,
Ed
You shouldn't have to do anything. The DefaultModelBinder will bind your form values to the parameter object without specifying Consumes or FromForm attributes. The same is also true for .NET Core.
Edit - code for clarity:
Also an important note: this (automatic form binding) will only work if you do NOT have the [ApiController] attribute tagging your controller.
Assume you have three hidden fields coming in, one is named foo, the other is named fudge
Either one of these will work:
[HttpPost]
public void Webhook(string foo, string fudge)
{
}
or:
public class WbResponse
{
public string foo {get; set;}
public string fudge {get; set;}
}
[HttpPost]
public void Webhook(WbResponse response)
{
}
Turns out that the request object contains all the hidden fields in its "Form" member which is a NameValueCollection. I declared my method like this:
// POST: /{Controller}/Webhook
[HttpPost]
public virtual ActionResult Webhook()
{
var requestFormFields = HttpContext.Request.Form;
and then I can access each field in the NameValueCollection by its name:
var hiddenFieldValue = requestFormFields["hiddenFieldName"];

Understanding about constructor in Web Api

My web api looks like:
[Route("api/[controller]")]
public class ValuesController : Controller
{
private readonly ApplicationDbContext _context;
public ValuesController(ApplicationDbContext context)
{
_context = context;
}
[HttpGet]
public string Get()
{
// get random user
var user = _context.Users.SingleOrDefault();
return user?.Email ?? "";
}
}
Trying to call it via jquery:
$.get('/api/values', function (email) {
console.log(email)
})
I've 2 questions:
1/. Why didn't console.log(email) work although I was getting the response successful?
There was nothing in the Console tab.
2/. When I made a request to server (/api/values), the breakpoint had been caught:
My question: where had ValuesController been called within context? I'd sent a request from client, then the constructor was hit (I'm sure that I didn't send something like ApplicationDbContext from client to server :v)
UPDATE: By changing $.get('/api/values', {}, function (email) {} to $.get('/api/values', function (email) {}. I've fixed the first problem. It's my bad. Sorry about that.
Shorter Answer
My question: where had ValuesController been called within context? I'd sent a request from client, then the constructor was hit.
The HTTP Request arrived. ASP.NET MVC Routing told the application to use the ValuesController to handle the request. The application constructed the ValuesController, supplying an instance of ApplicationDbContext via dependency injection.
Longer Answer
The Startup.Configure method is used to specify how the ASP.NET application will respond to individual HTTP requests. Since you are using Web API, you have configured app.UseMvc(). Result: when an HTTP Request arrives, MVC Routing tells the application to use the appropriate controller.
The Startup.ConfigureServices method is used to specify services that are available via dependency injection. Since you are injecting an ApplicationDbContext into your constructor, you have configured services.AddDbContext<ApplicationDbContext>(). Result: when the application constructs a ValuesController, ASP.NET Dependency Injection will provide an instance of the ApplicationDbContext.

what is the best way to consume web api in mvc

I am using web api in my mvc application. I have method in web api which returns user detail using userId (which is in session["userID"])
public object getUserDetail()
{
//here is need of session["userID"]
// return somthing
}
so what is best way to access this web api method from jquery . Should i access this directly or first i should call my controller method and from there i should call this web api method.
You can directly call WebApi from jquery for performing operations(like insert/update/delete)other than returning JSON for processing back. For the scenarios where you require manipulating your view, call mvc controller which calls the Webapi.
So, for your case, the getUserDetail() method returns data. If these return values needs to be used in your view, then call it from mvc controller
WebApi is already an exposed endpoint for you to access your data from. Going to your controller, and calling the method from there diminishes the intent of having exposed the method as an Api in the first place. Try making a call to the route of the Api method, and you should be fine.
On a side note, try exposing a strongly typed object instead of just returning an object.
what is best way to access this web api method from jquery
Simply make an ajax call.
var url = www.example.com/api/user;
$.ajax({
type: 'GET',
url: url,
success: function(userValue) {
// Do something with your user info...
},
error: function(error) {
// Something went wrong. Handle error.
}
});
And have your controller return the value.
public class UserController : ApiController
{
[HttpGet] // For clarity only
public object Get()
{
// return your object.
return session["userID"];
}
}
And to get your url for the controller, you can use this in your view.
Url.HttpRouteUrl("DefaultApi", new {controller = "UserController "})})
Where DefaultApi is the route name defined in your route table (usually in RouteConfig.cs).
Edit:
Regarding access to session there's a number of ways to get around it. Take a look at this question and I think you will solve it. Accessing Session Using ASP.NET Web API
Or this tutorial:
http://www.codeproject.com/Tips/513522/Providing-session-state-in-ASP-NET-WebAPI
public class SessionableControllerHandler : HttpControllerHandler, IRequiresSessionState
{
public SessionableControllerHandler(RouteData routeData)
: base(routeData)
{}
}
public class SessionStateRouteHandler : IRouteHandler
{
IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
{
return new SessionableControllerHandler(requestContext.RouteData);
}
}
And lastly register it with your route:
RouteTable.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
).RouteHandler = new SessionStateRouteHandler();
Or add this to your Global.asax.cs
protected void Application_PostAuthorizeRequest()
{
System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
}
Feels like you might want to step back and rethink the basics. The main question here is: does it sound right that one view layer (MVC) calls another view layer (web api)? And simple answer is: no.
Usual setup is that your ajax calls target your Web Api controller methods directly. But if for whatever reason you find yourself thinking that you really need your MVC to call WebApi then that looks for extracting business logic to separate layer/tier so what you end up with is both, MVC and Web API, calling same method in separate class/layer (whatever your methods actually do).
So, instead of:
//this is in your MVC controller
public ActionResult SomeMVCAction(){
MyWebApiMethod();
}
//This is in your web api controller
public SomeStrongType MyWebApiMethod(){
var sum = 2+2;
}
you might want to have something like:
//this is in your MVC controller
public ActionResult SomeMVCAction(){
DoSum();
}
//This is in your web api controller
public SomeStrongType MyWebApiMethod(){
DoSum()
}
///This function is defined in separate layer/project which is your business layer
public static int DoSum(){
return 2+2;
}
PS.
Regarding session...There is a reason why session is not (easily) accessible in WebApi. REST Api should be stateless so you might want to rethink your design where you need session in web api controller.
You can describe a problem you're trying to solve by accessing session in web api controller and then we can try to give opinion on that.

Asp.net Web Api get request header

I have an Api project in that I have 2 different Controllers :
one controller is a System.Web.Mvc controller:
public class HomeController : Controller
in that, I have define a request like below:
var request = System.Web.HttpContext.Current.Request;
request.Headers.Add("token", "test");
one other controller is a Api controller:
public class CalendarController : ApiController
{
private string _accessToken;
public CalendarController()
{
IEnumerable<string> accessTokenValues;
var request = System.Web.HttpContext.Current.Request;
var token = request.Headers.GetValues("token");
//var tokenValues = accessTokenValues as string[] ?? accessTokenValues.ToArray();
//_accessToken = (tokenValues.Any()) ? tokenValues.First() : "";
} }
I added "token" to the request header but I cannot get it in the Api controller. Please help me !
Thanks!
The originating caller is responsible for setting the request headers. Therefore adding your header on the first request to HomeController means that it will not be added to subsequent requests to CalendarController. Take a look at : https://msdn.microsoft.com/en-us/library/bb470252.aspx for more details about the ASP.NET request response pipeline
Ultimately, it depends on what you want to achieve as to how you might add to the header.
For example, If you have all the information on the server side to add to the request header and you're using OWIN you can add a custom middle-ware layer that will intercept incoming calls and add your custom header as the request makes its way to your controller.(http://www.asp.net/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline)

Get an instance of WebApi UrlHelper from inside an Mvc Action

I am running WebApi and Mvc from within the same project (so they are in-process). Mvc mostly for serving assets (pages and generated downloads) and web api for ajax data requests.
In order to be RESTish, most of the WebApi requests include a set of links where are generated by the following class:
public class ApiLinkMaker
{
public ApiLinkMaker(UrlHelper url, string authority) {
this.url = url;
this.authority = authority;
}
public ApiLinkMaker(ApiController controller)
: this(controller.Url, controller.Request.RequestUri.Authority) { }
public string MakeLink(string controller, string id) {
return "//" + authority + url.Route("DefaultApi", new { controller = controller, id = id });
}
}
There's a few other methods on there, but this is really the core of things and it works fine.
Now I want to optimize a particular page. Where previously I had two requests
Download the html
Do an Ajax query to get some data (and some links)
Now I realize that for optimization purposes it is better to do just one in this case.
Download the html with the data already JSON embedded into it.
The problem is that since the html is being generated by Mvc, I cannot create an Api UrlHelper that seems to work.
I tried
var url = new UrlHelper(new HttpRequestMessage(verb, controller.Request.Url.AbsoluteUri));
if (!url.Request.Properties.ContainsKey(HttpPropertyKeys.HttpConfigurationKey)) //http://stackoverflow.com/questions/11053598/how-to-mock-the-createresponset-extension-method-on-httprequestmessage
url.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
But this still blows up
System.ArgumentException was unhandled by user code
HResult=-2147024809
Message=A route named 'DefaultApi' could not be found in the route collection.
Parameter name: name
Source=System.Web.Http
ParamName=name
StackTrace:
at System.Web.Http.HttpRouteCollection.GetVirtualPath(HttpRequestMessage request, String name, IDictionary`2 values)
at System.Web.Http.Routing.UrlHelper.GetHttpRouteHelper(HttpRequestMessage request, String routeName, IDictionary`2 routeValues)
at System.Web.Http.Routing.UrlHelper.GetHttpRouteHelper(HttpRequestMessage request, String routeName, Object routeValues)
at System.Web.Http.Routing.UrlHelper.Route(String routeName, Object routeValues)
at MyProject.Models.ApiLinkMaker.MakeLink(String controller, String id) in w:\MyProject\Models\ApiLinkMaker.cs:line 42
...
This leads me to think that I'm going about this wrong - that I need to create the url helper from the api routing configuration somehow.
Why create one? There is an instance of the UriHelper exposed as a property on both the MVC Controller and ApiController classes.
public ActionResult Index()
{
string url = Url.RouteUrl("DefaultApi", new {httproute = "", controller = "test"});
return View();
}
Edit: Updated code. While the url helpers are different you can use the MVC url helper to resolve the web api url.
Edit2: The correct method to use if you want to get webapi routes from an Mvc UrlHelper is
string url = Url.HttpRouteUrl("DefaultApi", new {httproute = "", controller = "test"});

Resources