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

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

Related

ASP.NET core web API routing not supported in AWS HTTP API Gateway?

I am trying to transfer an asp.net core web api to my first AWS HTTP API.
I have hosted the asp.net core web api project as a lambda function, and trying to match the endpoints through the API gateway.
I can access the default endpoints though my API gateway. i.e. the following endpoint can be accessed through my api gateway successfully.
[Route("api/[controller]")]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value10", "value200" };
}
...
}
But, I get a 404 not found exception if I try to access some method with a Route attribute. e.g.
[Route("api/[controller]")]
[ApiController]
public class ReportsController : ControllerBase
{
// GET api/values
[HttpGet, Route("GetReports")]
public IEnumerable<string> GetReports()
{
return new string[] { "value100", "value2000" };
}
}
with the following mapping
What am I doing wrong here?
thanks,

Bearer token: The signature is invalid - Default ASP.NET Core 2.1 Web Api template published to Azure

I created a project in VS Community 2019 (latest update) with a template for WebApi .NET Core 2.1 and published it on Azure.
I only added a client secret in the app registration in the portal to use for the call using the authorization code flow.
I was trying to make a GET call using Postman with OAuth 2.0 authorization at the url below:
https://webapi3app.azurewebsites.net/api/values
But I get an unauthorized response with the error header below:
WWW-Authenticate:"Bearer error="invalid_token", error_description="The signature is invalid""
I tried decoding the client secret to BASE64 string but in the repsonse it says that it's an invalid client secret.
I tried changing authorization data to:
- Request URL.
- Request Headers.
I tried several grant types:
- Authorization code.
- Implicit.
- Password Credentials (after changing app to public client).
I tried several scopes:
- Default Microsoft scopes url (https://graph.microsoft.com/.default).
- user.read openid profile offline_access.
- https://aldolekalive.onmicrosoft.com/WebApi3/user_impersonation.
- profile openid email https://graph.microsoft.com/Directory.Read.All https://graph.microsoft.com/User.Read
I tried setting client authentication to:
- Send as basic auth header.
- Send client credentials in body.
I tried changing the Authorize attribute to authorize based on only AzureADBearer or only AzureADJwtBearer (because apparently by default they are both enabled with the current configuration) but no luck.
etc.
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.AzureAD.UI;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
.AddAzureADBearer(options => Configuration.Bind("AzureAd", options));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseMvc();
}
}
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
}
I expect to get a response with the body:
"value1, value2"
Per my understanding, your webapi is protected by Azure AD and now you want to call the api. To call the api you need to provide an access token.
To do this, you need to register two applications in Azure AD. One is for client App, the other one is for webapi. You can refer to my answer here.
And here is the complete sample. If you don't have an client application now, you can just register an client app in Azure portal, then use this client app to get an access token for your webapi.
I tried several scopes:
If you are using v2.0 endpoint, the scope should be api://{server_client_id}/.default.

WebApi with OWIN SelfHost and Windows Authentication

I have a console application SERVER that hosts WebApi controllers using OWIN self-hosting, and runs under a custom account named "ServiceTest1".
In the same machine I have another console application CLIENT that runs under the account "ServiceTest2", and I want to capture in SERVER that "ServiceTest2" invoked a controller action. However:
WindowsIdentity.GetCurrent() is always "ServiceTest1".
Thread.CurrentPrincipal is an unauthenticated GenericIdentity.
RequestContext.Principal is null.
User is null.
What do I need to make this WebApi OWIN self-hosted to grab the Windows identity of the caller?
Your question is a little unclear on exactly how you've implemented the Windows authentication.
Enable Windows authentication:
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpListener listener = (HttpListener)app.Properties["System.Net.HttpListener"];
listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;
// ...
}
}
Get the user in an OWIN middleware:
public async Task Invoke(IDictionary<string, object> env)
{
OwinContext context = new OwinContext(env);
WindowsPrincipal user = context.Request.User as WindowsPrincipal;
//...
}
Get the user in a Web API Controller:
// In a web api controller function
WindowsPrincipal user = RequestContext.Principal as WindowsPrincipal;

ASP.NET Web API session or something?

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

How to set up Elmah with ASP.NET Web API

I've tried many elmah nugets but they didn't work with ASP.NET Web API. Does anybody knows why? Is there any work around for that?
There are two options by using ELMAH to capture exceptions in WEB API.
If you want to capture errors that are encountered in Actions and Controllers , i.e. in your business logic you can create a ActionFilterAttribute and log those exceptions to ELMAH.
example:
public class UnhandledExceptionFilter : ExceptionFilterAttribute {
public override void OnException(HttpActionExecutedContext context) {
Elmah.ErrorLog.GetDefault(HttpContext.Current).Log(new Elmah.Error(context.Exception));
}
}
Then wireup by adding that filter.
public static class WebApiConfig {
public static void Register(HttpConfiguration config) {
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Filters.Add(new UnhandledExceptionFilter());
}
}
With the above approach following errors will not be handled:
Exceptions thrown from controller constructors.
Exceptions thrown from message handlers.
Exceptions thrown during routing.
Exceptions thrown during response content serialization
Reference: http://blogs.msdn.com/b/webdev/archive/2012/11/16/capturing-unhandled-exceptions-in-asp-net-web-api-s-with-elmah.aspx & http://www.asp.net/web-api/overview/error-handling/web-api-global-error-handling
In order for ELMAH to log WEB API errors at the global level such that all 500 Server errors are caught then do this:
Install nuget: https://www.nuget.org/packages/Elmah.Contrib.WebApi/
Add the below to WebApiConfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
...
config.Services.Add(typeof(IExceptionLogger), new ElmahExceptionLogger());
...
}
}
And if you want to show custom error messages for the 500 Server errors you can implement the new ExceptionHandler in Web Api (Note that ExceptionLogger and ExceptionHandler are different.)
class OopsExceptionHandler : ExceptionHandler
{
public override void HandleCore(ExceptionHandlerContext context)
{
context.Result = new TextPlainErrorResult
{
Request = context.ExceptionContext.Request,
Content = "Oops! Sorry! Something went wrong." +
"Please contact support#contoso.com so we can try to fix it."
};
}
private class TextPlainErrorResult : IHttpActionResult
{
public HttpRequestMessage Request { get; set; }
public string Content { get; set; }
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response =
new HttpResponseMessage(HttpStatusCode.InternalServerError);
response.Content = new StringContent(Content);
response.RequestMessage = Request;
return Task.FromResult(response);
}
}
}
Reference: http://www.asp.net/web-api/overview/error-handling/web-api-global-error-handling
one option would be to setup a custom ExceptionFilterAttribute, override the OnException method, and signal Elmah from there. See the sample link below
Elmah WebAPI Sample
Check the below URL it describe in details how to use elmah with Web API:
http://blogs.msdn.com/b/webdev/archive/2012/11/16/capturing-unhandled-exceptions-in-asp-net-web-api-s-with-elmah.aspx
You can also use the NuGet Package below:
Install-Package Elmah.Contrib.WebApi
Usage:
Simply register it during your application's start up, or on a controller-by-controller basis.
protected void Application_Start()
{
GlobalConfiguration.Configuration.Filters.Add(new ElmahHandleErrorApiAttribute());
...
}
(from the Elmah.Contrib.WebApi GitHub repo)
For ASP.NET Web API use the Elmah.MVC nuget package, details of which are given below
Taken from : HOW TO SETUP ELMAH.MVC WITH ASP.NET MVC 4 ?
What is Elmah ?
ELMAH is an open source project whose purpose is to log and report unhandled exceptions in ASP.NET web applications.
Why to use Elmah ?
ELMAH serves as an unobtrusive interceptor of unhandled ASP.NET exceptions, those usually manifesting with the ASP.NET yellow screen of death.
So now we know what and why to use Elmah, Lets quickly get started on how to use Elmah with your ASP.NET MVC project.
Step 1: Right click on your solution and select the "Manage Nuget Packages" option
Step 2: In the Nuget Package manager search for "Elmah" and install the Elmah.MVC nuget extension.
The Nuget Package manager will download and add the required dlls and modify the web.config's <appSetting> for Elmah to work.
Step 3: That's it !! Your Elmah is now ready to test. I have generated a 404 to test if my Elmah works, ELMAH can be accessed by this url : http://yourapp.com/elmah.
Hope this helps :)
Further Reading :
Elmah on code.google.com
Elmah.MVC 2.0.2 on Nuget
Elmah.MVC on GitHub

Resources