how to get HttpContext.Current.GetOwinContext() in startup - asp.net

I very read for this problem but i can not fixed this so i think create a new question in this site.
HttpContext.Current.GetOwinContext();
i want get GetOwinContext values with above code . above code there are in my startup.cs
[assembly: OwinStartupAttribute(typeof(OwinTest.Startup))]
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
var c = HttpContext.Current.GetOwinContext();
}
}
and i get this error
//No owin.Environment item was found in the context
but var c = HttpContext.Current.GetOwinContext(); work for me in HomeController fine.!
I just get GetOwinContext in my startup.cs class.
thankfull

You can't do that. The OWIN context does not exist without a request, and the Startup class only runs once for the application, not for each request. Your Startup class should initialize your middleware and your application and the middleware and the application should access the OWIN context when needed.

As mentioned, what you are asking isn't possible. However, depending on your requirements, the following is possible and gives you access within the context of creating object instances. This is something I needed in order to check for whether an instance was already added else where (I have multiple startup classes in different projects).
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
// Ensure we have our "main" access setup
app.CreatePerOwinContext<DataAccessor>(
(options, owinContext) =>
{
// Check that an instance hasn't already been added to
// the OwinContext in another plugin
return owinContext.Get<DataAccessor>() ?? DataAccessor.CreateInstance(options, owinContext);
}
);
}
Within the CreatePerOwinContext we have access to the OwinContext, so we can access it at the point of creating a new type. This might not help everyone as it's a little more specific to a person's needs, but is useful to know.

Related

Consume OpenApi client .NET Core with Interface

Someone out there must have run into this already...
I created a WebApi solution with swagger implemented, full documentation, the whole 9 yards!
When I run my web api solution, see the swagger output (and I've tested the endpoints, all working fine)
I can see the swagger definition: https://localhost:5001/swagger/v1/swagger.json
Now, I want to consume this Api as a connected service on my web app.
So following every single tutorial online:
I go to my webapp
right click on Connected Services
Add Connected Service
Add Service Reference > OpenApi > add Url, namespace & class name
That generates a partial class in my solution (MyTestApiClient)
public parial class MyTestApiClient
{
// auto generated code
}
Next step, inject the service in Startup.cs
services.AddTransient(x =>
{
var client = new MyTestApiClient("https://localhost:5001", new HttpClient());
return client;
});
Then, inject the class into some class where it's consumed and this all works
public class TestService
{
private readonly MyTestApiClient _client; // this is class, not an interface -> my problem
public TestService(MyTestApiClient client)
{
_client = client;
}
public async Task<int> GetCountAsync()
{
return _client.GetCountAsync();
}
}
So everything up to here works. BUT, this generated OpenApi client doesn't have an interface which sucks for the purposes of DI and Unit Testing.
I got around this by creating a local interface IMyTestApiClient, added to the generated class (MyTestApiClient). I only have 1 endpoint in my WebApi so have to declare that on my interface.
public parial class MyTestApiClient : IMyTestApiClient
{
// auto generated code
}
public interface IMyTestApiClient
{
// implemented in generated MyTestApiClient class
Task<int> GetCountAsync();
}
services.AddTransient<IMyTestApiClient, MyTestApiClient>(x =>
{
IMyTestApiClient client = new MyTestApiClient("https://localhost:5001", new HttpClient());
return client;
});
public class TestService
{
private readonly IMyTestApiClient _client; // now injecting local interface instead of the generated class - great success
public TestService(IMyTestApiClient client)
{
_client = client;
}
public async Task<int> GetCountAsync()
{
return _client.GetCountAsync();
}
}
But this is a bad approach because it makes me manually create an interface and explicitly declare the methods I want to consume. Furthermore, every time my Api gets updated, I will have to tweak my local interface.
So question time:
How can I add an OpenApi Service Reference that automagically also generates an interface as well?
Thanks in advance for any help getting to a viable solution.
You may have already found the answer but I had the same issue and managed to resolve it by adding /GenerateClientInterfaces:true in the Options section for the OpenAPI reference in my .csproj:
<OpenApiReference Include="api.json" CodeGenerator="NSwagCSharp" Namespace="MyNamespace" ClassName="MyClassName">
<SourceUri>https://localhost:7040/swagger/v1/swagger.json</SourceUri>
<OutputPath>MyClient.cs</OutputPath>
<Options>/GenerateClientInterfaces:true</Options>
</OpenApiReference>

Use session variables in to Hangfire Recurring Job

I have integrated hangfire in to Asp.net web application and trying to use session variables in to Hangfire Recurring Job as like below :
public class Startup
{
public void Configuration(IAppBuilder app)
{
HangfireSyncServices objSync = new HangfireSyncServices();
var options = new DashboardOptions
{
Authorization = new[] { new CustomAuthorizationFilter() }
};
app.UseHangfireDashboard("/hangfire", options);
app.UseHangfireServer();
//Recurring Job
RecurringJob.AddOrUpdate("ADDRESS_SYNC", () => objSync.ADDRESS_SYNC(), Cron.MinuteInterval(30));
}
}
My “HangfireSyncServices” class as below:
public partial class HangfireSyncServices : APIPageClass
{
public void ADDRESS_SYNC()
{
string userName = Convert.ToString(Session[Constants.Sessions.LoggedInUser]).ToUpper();
//Exception throwing on above statement..
//........Rest code.......
}
}
public abstract class APIPageClass : System.Web.UI.Page
{
//common property & methods...
}
but I am getting run time exception as below at the time of getting value in to “userName”:
Session state can only be used when enableSessionState is set to true, either in a configuration file or in the Page directive. Please also make sure that System.Web.SessionStateModule or a custom session state module is included in the
section in the application configuration.
I have tried to resolve above error using this LINK & other solution also but not able to resolved yet. can anyone help me on this issue.
Thanks in advance,
Hiren
Hangfire jobs don't run in the same context as asp.net, it has it's own thread pool. In fact, Hangfire jobs may even execute on a different server than the one that queued the job if you have multiple servers in your hangfire pool.
Any data that you want to have access to from within the job needs to be passed in as a method parameter. For example:
public partial class HangfireSyncServices //: APIPageClass <- you can't do this..
{
public void ADDRESS_SYNC(string userName)
{
//........Rest code.......
}
}
string userName = Convert.ToString(Session[Constants.Sessions.LoggedInUser]).ToUpper();
RecurringJob.AddOrUpdate("ADDRESS_SYNC", () => objSync.ADDRESS_SYNC(userName), Cron.MinuteInterval(30));
Note that doing the above creates a recurring task that will always execute for the same user, the one that was triggered the web request that created the job.
Next problem: you're trying to create this job in the server startup, so there is no session yet. You only get a session when a web request is in progress. I can't help you with that because I don't have any idea what you're actually trying to do.

How to use ResourceProcessorHandlerMethodReturnValueHandler in a spring-hateos project

When using spring-data-rest there is a post processing of Resource classes returned from Controllers (e.g. RepositoryRestControllers). The proper ResourceProcessor is called in the post processing.
The class responsible for this is ResourceProcessorHandlerMethodReturnValueHandler which is part of spring-hateoas.
I now have a project that only uses spring-hateoas and I wonder how to configure ResourceProcessorHandlerMethodReturnValueHandler in such a scenario. It looks like the auto configuration part of it still resides in spring-data-rest.
Any hints on how to enable ResourceProcessorHandlerMethodReturnValueHandler in a spring-hateoas context?
I've been looking at this recently too, and documentation on how to achieve this is non-existent. If you create a bean of type ResourceProcessorInvokingHandlerAdapter, you seem to lose the the auto-configured RequestMappingHandlerAdapter and all its features. As such, I wanted to avoid using this bean or losing the WebMvcAutoConfiguration, since all I really wanted was the ResourceProcessorHandlerMethodReturnValueHandler.
You can't just add a ResourceProcessorHandlerMethodReturnValueHandler via WebMvcConfigurer.addReturnValueHandlers, because what we need to do is actually override the entire list, as is what happens in ResourceProcessorInvokingHandlerAdapter.afterPropertiesSet:
#Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
// Retrieve actual handlers to use as delegate
HandlerMethodReturnValueHandlerComposite oldHandlers = getReturnValueHandlersComposite();
// Set up ResourceProcessingHandlerMethodResolver to delegate to originally configured ones
List<HandlerMethodReturnValueHandler> newHandlers = new ArrayList<HandlerMethodReturnValueHandler>();
newHandlers.add(new ResourceProcessorHandlerMethodReturnValueHandler(oldHandlers, invoker));
// Configure the new handler to be used
this.setReturnValueHandlers(newHandlers);
}
So, without a better solution available, I added a BeanPostProcessor to handle setting the List of handlers on an existing RequestMappingHandlerAdapter:
#Component
#RequiredArgsConstructor
#ConditionalOnBean(ResourceProcessor.class)
public class ResourceProcessorHandlerMethodReturnValueHandlerConfigurer implements BeanPostProcessor {
private final Collection<ResourceProcessor<?>> resourceProcessors;
#Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof RequestMappingHandlerAdapter) {
RequestMappingHandlerAdapter requestMappingHandlerAdapter = (RequestMappingHandlerAdapter) bean;
List<HandlerMethodReturnValueHandler> handlers =
requestMappingHandlerAdapter.getReturnValueHandlers();
HandlerMethodReturnValueHandlerComposite delegate =
handlers instanceof HandlerMethodReturnValueHandlerComposite ?
(HandlerMethodReturnValueHandlerComposite) handlers :
new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
requestMappingHandlerAdapter.setReturnValueHandlers(Arrays.asList(
new ResourceProcessorHandlerMethodReturnValueHandler(delegate,
new ResourceProcessorInvoker(resourceProcessors))));
return requestMappingHandlerAdapter;
}
else return bean;
}
}
This has seemed to work so far...

In ASP.NET 5, how do I get the chosen route in middleware?

I am building an ASP.NET 5 (vNext) site that will host dynamic pages, static content, and a REST Web API. I have found examples of how to create middleware using the new ASP.NET way of doing things but I hit a snag.
I am trying write my own authentication middleware. I would like to create a custom attribute to attach to the controller actions (or whole controllers) that specifies that it requires authentication. Then during a request, in my middleware, I would like to cross reference the list of actions that require authentication with the action that applies to this current request. It is my understanding that I configure my middleware before the MVC middleware so that it is called first in the pipeline. I need to do this so the authentication is done before the request is handled by the MVC controller so that I can't prevent the controller from ever being called if necessary. But doesn't this also mean that the MVC router hasn't determined my route yet? It appears to me the determination of the route and the execution of that routes action happen at one step in the pipeline right?
If I want to be able to determine if a request matches a controller's action in a middleware pipeline step that happens before the request is handled by the controller, am I going to have to write my own url parser to figure that out? Is there some way to get at the routing data for the request before it is actually handled by the controller?
Edit: I'm beginning to think that the RouterMiddleware might be the answer I'm looking for. I'm assuming I can figure out how to have my router pick up the same routes that the standard MVC router is using (I use attribute routing) and have my router (really authenticator) mark the request as not handled when it succeeds authentication so that the default mvc router does the actual request handling. I really don't want to fully implement all of what the MVC middleware is doing. Working on trying to figure it out. RouterMiddleware kind of shows me what I need to do I think.
Edit 2: Here is a template for the middleware in ASP.NET 5
public class TokenAuthentication
{
private readonly RequestDelegate _next;
public TokenAuthentication(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
//do stuff here
//let next thing in the pipeline go
await _next(context);
//do exit code
}
}
I ended up looking through the ASP.NET source code (because it is open source now!) and found that I could copy the UseMvc extension method from this class and swap out the default handler for my own.
public static class TokenAuthenticationExtensions
{
public static IApplicationBuilder UseTokenAuthentication(this IApplicationBuilder app, Action<IRouteBuilder> configureRoutes)
{
var routes = new RouteBuilder
{
DefaultHandler = new TokenRouteHandler(),
ServiceProvider = app.ApplicationServices
};
configureRoutes(routes);
routes.Routes.Insert(0, AttributeRouting.CreateAttributeMegaRoute(
routes.DefaultHandler,
app.ApplicationServices));
return app.UseRouter(routes.Build());
}
}
Then you create your own version of this class. In my case I don't actually want to invoke the actions. I will let the typical Mvc middleware do that. Since that is the case I gut all the related code and kept just what I needed to get the route data which is in actionDescriptor variable. I probably can remove the code dealing with backing up the route data since I dont think what I will be doing will affect the data, but I have kept it in the example. This is the skeleton of what I will start with based on the mvc route handler.
public class TokenRouteHandler : IRouter
{
private IActionSelector _actionSelector;
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
EnsureServices(context.Context);
context.IsBound = _actionSelector.HasValidAction(context);
return null;
}
public async Task RouteAsync(RouteContext context)
{
var services = context.HttpContext.RequestServices;
EnsureServices(context.HttpContext);
var actionDescriptor = await _actionSelector.SelectAsync(context);
if (actionDescriptor == null)
{
return;
}
var oldRouteData = context.RouteData;
var newRouteData = new RouteData(oldRouteData);
if (actionDescriptor.RouteValueDefaults != null)
{
foreach (var kvp in actionDescriptor.RouteValueDefaults)
{
if (!newRouteData.Values.ContainsKey(kvp.Key))
{
newRouteData.Values.Add(kvp.Key, kvp.Value);
}
}
}
try
{
context.RouteData = newRouteData;
//Authentication code will go here <-----------
var authenticated = true;
if (!authenticated)
{
context.IsHandled = true;
}
}
finally
{
if (!context.IsHandled)
{
context.RouteData = oldRouteData;
}
}
}
private void EnsureServices(HttpContext context)
{
if (_actionSelector == null)
{
_actionSelector = context.RequestServices.GetRequiredService<IActionSelector>();
}
}
}
And finally, in the Startup.cs file's Configure method at the end of the pipeline I have it setup so that I use the same routing setup (I use attribute routing) for the both my token authentication and mvc router.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//Other middleware delcartions here <----------------
Action<IRouteBuilder> routeBuilder = routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
};
app.UseTokenAuthentication(routeBuilder);
//Middleware after this point will be blocked if authentication fails by having the TokenRouteHandler setting context.IsHandled to true
app.UseMvc(routeBuilder);
}
Edit 1:
I should also note that at the moment I am not concerned about the extra time required to select the route twice which is what I think would happen here since both my middleware and the Mvc middleware will be doing that. If that becomes a performance problem then I will build the mvc and authentication in to one handler. That would be best idea performance-wise, but what I have shown here is the most modular approach I think.
Edit 2:
In the end to get the information I needed I had to cast the ActionDescriptor to a ControllerActionDescriptor. I am not sure what other types of actions you can have in ASP.NET but I am pretty sure all my action descriptors should be ControllerActionDescriptors. Maybe the old legacy Web Api stuff needs another type of ActionDescriptor.

ASP.NET - Create custom context object?

How do I create a globally accessible Context object similar to the HttpContext object?
I want to create a custom class library which I want to reference from a website project. In the website project I want to be able to call the following globally:
ClassLibraryName.Context
I cannot create a global property directly in my classlibrary, so how should this be implemented? (I've seen other applications/products use this approach, one of which is Sitecore which has a custom Sitecore.Context object available)
Edit
Might this be a 'valid' solution?
namespace MyLibrary
{
public class Context
{
public static object ContextualObject
{
get;
set;
}
}
}
Yes, this is not hard to implement, if you always run this class in the context of an ASP.NET application, use this approach:
namespace MyLibrary
{
public class Context
{
public static object ContextualObject
{
get
{
var ctx = System.Web.HttpContext.Current.Items[typeof(Context)];
if (ctx == null)
{
ctx = new Context();
System.Web.HttpContext.Current.Items.Add(typeof(Context), ctx);
}
return ctx;
}
set { System.Web.HttpContext.Current.Items[typeof(Context)] = ctx; }
}
}
}
Essentially wrapping the existing HTTP context to provide your own service. This approach also doesn't store the object while the app lives, it only creates it for the current context, and when that response ends, it will die, and be regenerated during the next lifecycle. If that is not OK, store a static reference to context.
I've used this approach similarly in a class library I have at http://nucleo.codeplex.com, it works well.
HTH.
It depends on the lifetime you want the Context object to have. If you want all clients to use the same context, you can go with a singleton implementation.
If you want the context to be unique for each thread or http request you have to use a per request/thread implementation. One way to implement a per http request implementation would be to have a HttpModule create the object at every BeginRequest event and stick it in the HttpContext Items collection.
public static object ContextualObject
{
get { return HttpContext.Current.Items["MyContext"];}
}
You could create an instance of the object on Session_Start in the Global.asax.

Resources