ASP.NET Web API session or something? - session

I need to store some information in session(or in whatever in ASP.NET Web API) that I need to retrieve in every API request. We will have one api IIS web site and multiple web site binding will be added through host header. When any request comes in for example, api.xyz.com, host header will be checked and store that website information in session that will be used in each subsequent api request when making a call to database.
I know there is no support for session in ASP.NET Web API. Is there any other way to handle this kind of situation? Where can I store information that can be retrieving in each subsequent request?
thanks.

in Global.asax add
public override void Init()
{
this.PostAuthenticateRequest += MvcApplication_PostAuthenticateRequest;
base.Init();
}
void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e)
{
System.Web.HttpContext.Current.SetSessionStateBehavior(
SessionStateBehavior.Required);
}
give it a shot ;)

Well, REST by design is stateless. By adding session (or anything else of that kind) you are making it stateful and defeating any purpose of having a RESTful API.
The whole idea of RESTful service is that every resource is uniquely addressable using a universal syntax for use in hypermedia links and each HTTP request should carry enough information by itself for its recipient to process it to be in complete harmony with the stateless nature of HTTP".
So whatever you are trying to do with Web API here, should most likely be re-architectured if you wish to have a RESTful API.
With that said, if you are still willing to go down that route, there is a hacky way of adding session to Web API, and it's been posted by Imran here http://forums.asp.net/t/1780385.aspx/1
Code (though I wouldn't really recommend that):
public class MyHttpControllerHandler
: HttpControllerHandler, IRequiresSessionState
{
public MyHttpControllerHandler(RouteData routeData): base(routeData)
{ }
}
public class MyHttpControllerRouteHandler : HttpControllerRouteHandler
{
protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new MyHttpControllerHandler(requestContext.RouteData);
}
}
public class ValuesController : ApiController
{
public string GET(string input)
{
var session = HttpContext.Current.Session;
if (session != null)
{
if (session["Time"] == null)
{
session["Time"] = DateTime.Now;
}
return "Session Time: " + session["Time"] + input;
}
return "Session is not availabe" + input;
}
}
and then add the HttpControllerHandler to your API route:
route.RouteHandler = new MyHttpControllerRouteHandler();

In WebApi 2 you can add this to global.asax
protected void Application_PostAuthorizeRequest()
{
System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
}
Then you could access the session through:
HttpContext.Current.Session

You can use cookies if the data is small enough and does not present a security concern. The same HttpContext.Current based approach should work.
Request and response HTTP headers can also be used to pass information between service calls.

Now in 2017 with ASP.Net Core you can do it as explained here.
The Microsoft.AspNetCore.Session package provides middleware for managing session state.
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
// Adds a default in-memory implementation of IDistributedCache.
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
// Set a short timeout for easy testing.
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.Cookie.HttpOnly = true;
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseSession();
}
From the Docs:
Introduction to session and application state in ASP.NET Core
Already tested on a working project

Related

Session Value is Always null in ASP.NET Core Web API

I am trying to store the values in session in asp.net core web api project. I have referred the below link to store the values in session.
https://andrewlock.net/an-introduction-to-session-storage-in-asp-net-core/
But i am getting null always while getting session value.
You need provide more details about your codes which doesn't work. But basically you can refer to below steps:
Add ASP.NET Core 2.0 web api application .
Install Microsoft.AspNetCore.Session NuGet package .
Modify your Startup.cs, call AddDistributedMemoryCache and AddSession methods in ConfigureServices function , and add UseSession method in Configure function :
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDistributedMemoryCache();
services.AddSession();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseSession();
app.UseMvc();
}
Get/Set session in controller(using Microsoft.AspNetCore.Http;) :
[HttpGet("setSession/{name}")]
public IActionResult setsession(string name)
{
HttpContext.Session.SetString("Name", name);
return Ok("session data set");
}
[HttpGet("getSession")]
public IActionResult getsessiondata()
{
var sessionData = HttpContext.Session.GetString("Name");
return Ok(sessionData);
}
Then you could make api call to http://localhost:xxxxx/api/ControllerName/setSession/derek to set session , and call to http://localhost:xxxxx/api/ControllerName/getSession to get session data .
Following tutorial will help to set up Session values in server-side in ASP .Net Core Web API application.
Tutorial for Session in API Core

SignalR and Web Api - How to modify the Hub class

I am looking to notify clients of my Web Api that other clients have authenticated using SignalR. I understand the basics of SignalR but I am confused as to how to modify the Hub such that it can work with an API request.
The client is a Single Page Application which makes use of jQuery to call the Web Api. The client first authenticates with the API before it can use any of the API endpoints.
Also should add that I am authenticating with OAuth in the same project as the Web Api.
Well, the easiest way here is to get a reference to the signalR hub inside the oauth authentication flux, and then launch a global signaling after the successfull completion of this method: Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context).
For example:
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
// auth and other stuffs removed for brevity
// ...
// ...
context.Validated(ticket);
// then here
var hub = GlobalHost.ConnectionManager.GetHubContext<IMessageHub>("MessageHub");
hub.Clients.All.ServerMessage(new {message = $"{context.UserName} is here!"});
}
with a message hub like this:
public interface IMessageHub
{
void ServerMessage(object eventObject);
}
[HubName("MessageHub"), Authorize]
public class MessageHub : Hub<IMessageHub>
{
public MessageHub()
{
}
}
Hope it helps :)

Receiving files form PLUpload in WICKET

Im trying to integrate PLUpload into my wicket application. First steps are looking clear. Im able to choose files and when i click the "upload"-button i receive an request on server-side in my PLUploadBehavior based on AbstractDefaultAjaxBehavior. But it does not seems to be a MultiPart request.
public abstract class PLUploadBehavior extends AbstractDefaultAjaxBehavior {
public PLUploadBehavior() {
}
#Override
public void renderHead(final Component component, IHeaderResponse response) {
super.renderHead(component, response);
response.render(JavaScriptHeaderItem.forReference(new JavaScriptResourceReference(PLUploadBehavior.class, "plupload.full.min.js"));
StringBuffer script = new StringBuffer();
//build the init-script...
response.render(OnLoadHeaderItem.forScript(script.toString()));
}
#Override
protected void respond(AjaxRequestTarget target) {
Request request = getComponent().getRequest();
//received request here, but don't know hot to access files
if (request instanceof IMultipartWebRequest) {
System.out.println("Multipart!!!");
}
}
}
I followed the tutorial for plupload and have no form in my html template. There is none in the tutorial, so i think i don't need it. Anyone an idea to access the files on server-side?
After some more coffee i found the solution to my problem. The example on wicket in action can get adapted to the use with an Behavior. Thanks to Martin Grigorov and the great Wicket Team!

WebApi Per-Request Storage for Self Hosting Mode

When hosting WebApi is IIS, you have access to HttpContext and can use the items collection to store objects for a single HTTP request.
When self hosting, you no longer have a HttpContext, so what can I use to store an object for a single request ?
Obviously, there is no direct equivalent of System.Web's HttpContext in self-host.
However, if you wish to start info for the single request, then each HttpRequestMessage exposes a dictionary of <string,object>, called Properties - http://msdn.microsoft.com/en-us/library/system.net.http.httprequestmessage.properties.aspx which you can use to i.e. transport data between handlers, filters, binders and so on.
For selfhost (no IIS involved) you could construct an attribute class deriving from System.Web.Http.Filters.ActionFilterAttribute type (in the assembly system.web.http .net 4.0+). Then override OnActionExecuted method as below:
public class NoResponseCachingAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
if (actionExecutedContext.Response.Headers.CacheControl == null)
actionExecutedContext.Response.Headers.CacheControl = new System.Net.Http.Headers.CacheControlHeaderValue();
actionExecutedContext.Response.Headers.CacheControl.NoCache = true;
actionExecutedContext.Response.Headers.CacheControl.NoStore = true;
actionExecutedContext.Response.Headers.CacheControl.MustRevalidate = true;
base.OnActionExecuted(actionExecutedContext);
}
}
This approach worked for my application.

Is it possible to get around the Cross-Origin limitation when calling the Google Places API Web service?

Is it possible enable the Google Placess API WebService to allow cross-origin requests from my domain so that I can access the service directly from the browser? I'v been experimenting with the API-keys by creating a Browser API key and then adding my domain to the referers list, but to no avail. Not sure if that is what the refeferer property is for anyway.
Is this limitation by design, or am I missing something here?
Google Places API WebService is the service that I want to use. Neither the Places Autocomplete or Places Search in the Places Library are suitable for my particular requirement.
Cheers
Stian
This is a client-side based limitation, so the short answer is: no.
However there are websites and services that try to surmount this problem by using scripts (loading them on the fly).
Have a look here and here (these articles are about generic cross-domain AJAX requests)
The Places-API is also available inside the Maps-Javascript-API, you don't need to struggle with cross-origins there.
Let me say its impossible to get around .I tried using java instead the code just works for http request(i used here is for graph.facebook.com):
public class search {
private static String readAll(Reader rd) throws IOException {
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp);
}
return sb.toString();
}
public static JSONObject readJsonFromUrl(String url) throws IOException, JSONException {
InputStream is = new URL(url).openStream();
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String jsonText = readAll(rd);
JSONObject json = new JSONObject(jsonText);
return json;
} finally {
is.close();
}
}
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
System.getProperties().put("http.proxyHost", "172.16.0.2");
System.getProperties().put("http.proxyPort", "8080");
JSONObject json = readJsonFromUrl("http://maps.googleapis.com/maps/api/place/nearbysearch/json?key=AIzaSyBRlMLIdoTk-j4OZCucR47rVMLhMmvZVRw&type=hospital&location=12.8213125%2C80.0442&radius=500&_=1427359809583");
System.out.println(json.toString());
// System.out.println(json.get("about"));
// System.out.println("hello ");
}
}
If you replace the link with places api web search it will not work,the reason is that google does not give its services on HTTP domain,,, and my code only works on HTTP domain(not HTTPS)

Resources