Is GlobalConfiguration in System.Web.Http.WebHost compatible with Owin? - asp.net-web-api

I'm currently moving a WebApi 1 to a WebApi 2 project with OWIN.
In this piece of code GlobalConfiguration is in System.Web.Http.WebHost.
public class HandlerErrorFilterAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
var logFactory = GlobalConfiguration.Configuration.DependencyResolver
.GetService(typeof(ILoggerFactory)) as ILoggerFactory;
...
}
}
I think this is not Owin compatible, but I can't find how to rewrite this so I can access the dependency resolver.

I am not entirely clear about your question here...but GlobalConfiguration is comaptible with Owin middleware...There is also something called System.Web.Http.Owin which is an Web API Owin Adpater middleware...if you use this adapter then GlobalConfiguration must not be used...actually this is the same adapter which is used in case of Owin Selfhost scenario too...
if you are NOT using this adapter and just using other Owin middleware along with System.Web.Http.WebHost, then your above code should work just fine...are you seeing anything different?

Related

How to register a model binder in web api?

I'm trying to register a custom model binder in Web Api, but can't seem to find the correct way to do it.
System.ArgumentException: 'The service type SimpleModelBinderProvider is not supported.'
WebApiConfig.cs
using System.Web.Http;
using System.Web.ModelBinding;
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
...
var provider = new SimpleModelBinderProvider(typeof(CustomerIdentity), new CustomerIdentityModelBinder());
config.Services.Insert(typeof(SimpleModelBinderProvider), 0, provider);
...
}
}
I've tried SimpleModelBinderProvider and ModelBinderProvider.
What is the proper way to register a custom model binder in web api?
NOTE: I'm not using the ModelBinderAttribute on the class because it's in another assembly which would cause a circular-dependency (and because I don't like decorating classes with attributes).
NOTE: Starting to think this might be namespace related. The project has both MVC5 and WebApi2 in it.
Namespace Issue
I should have been using the namespaces:
// In the WebApiConfig.
using System.Web.Http.ModelBinding;
using System.Web.Http.ModelBinding.Binders;
// For the ModelBinder itself.
using System.Web.Http.Controllers;
using System.Web.Http.ModelBinding;
using System.Web.Http.ValueProviders;
Instead of:
using System.Web.ModelBinding;
The code was near identical as well as the class names, which is why it was hard to track down and figure out.

Configuring Spring MockMvc to use custom argument resolver before built-in ones

I have a straightforward test case. I have a controller which has a parameter of a type Spring doesn't support by default, so I wrote a custom resolver.
I create the mock mvc instance I'm using like so:
mvc = MockMvcBuilders.standaloneSetup(controller).setCustomArgumentResolvers(new GoogleOAuthUserResolver()).build();
However, Spring is also registering almost 30 other argument resolvers, one of which is general enough that it is getting used to resolve the argument before mine. How can I set or sort the resolvers so that mine is invoked first?
This worked for me without reflection:
#RequiredArgsConstructor
#Configuration
public class CustomerNumberArgumentResolverRegistration {
private final RequestMappingHandlerAdapter requestMappingHandlerAdapter;
#PostConstruct
public void prioritizeCustomArgumentResolver () {
final List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<>(Objects.requireNonNull(requestMappingHandlerAdapter.getArgumentResolvers()));
argumentResolvers.add(0, new CustomerNumberArgumentResolver());
requestMappingHandlerAdapter.setArgumentResolvers(argumentResolvers);
}
}
The issue was that the People class the Google OAuth library I am using extends Map and the mock servlet API provides no way to manipulate the order in which the handlers are registered.
I ended up using reflection to reach into the mocks guts and remove the offending handler.

Entity Framework Core 1.0 DbContext not scoped to http request

I understood by watching this video with Rowan Miller
https://channel9.msdn.com/Series/Whats-New-with-ASPNET-5/06
(at minute 22)
that the way of configuring Entity Framework Core (previously known as EF7) into an ASP.NET Core 1.0 app (previously known as ASP.NET 5) in Startup.cs is as follows:
public void ConfigureServices(IServiceCollection services)
{
//Entity Framework 7 scoped per request??
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<MyDbContext>(options =>
{
options
.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]);
});
//MVC 6
services.AddMvc();
}
and that this DbContext will be scoped to an http request so that whenever in the code throughout the http pipeline (including middleware or MVC) a DbContext is used, we know for sure that the instance injected by the DI container will be the same.
But the problem is that it does not seem to work that way. Within the lifetime of MVC it is true that the DbContext instance injected is the same, but as described here: Entity Framework Core 1.0 unit of work with Asp.Net Core middleware or Mvc filter
I am trying to plug into the pipeline the following middleware to achieve some kind of centralised Commit/Rollback after a controller finalises execution:
public class UnitOfWorkMiddleware
{
private readonly RequestDelegate _next;
private readonly MyDbContext _dbContext;
private readonly ILogger _logger;
public UnitOfWorkMiddleware(RequestDelegate next, MyDbContext dbContext, ILoggerFactory loggerFactory)
{
_next = next;
_dbContext = dbContext;
_logger = loggerFactory.CreateLogger<UnitOfWorkMiddleware>();
}
public async Task Invoke(HttpContext httpContext)
{
await _next.Invoke(httpContext);
_logger.LogInformation("Saving changes for unit of work if everything went good");
await _dbContext.SaveChangesAsync();
}
}
and this middleware is immediately before than MVC6 in the pipeline
//inside Configure(IApplicationBuilder app) in Startup.cs
app.UseMiddleware<UnitOfWorkMiddleware>();
app.UseMvcWithDefaultRoute();
The DbContext instance in my Middleware is not the same as the instance being injected during the MVC lifetime.
Is this expected? Shouldn't a DbContext be scoped to an http request? Is possible to achieve what I was trying to achieve?
The plan B would be to use an MVC 6 Global filter (if I can find some documentation on how to do this). I assume that being part of MVC 6 framework, the DbContext instance injected will be the same..
After more testing I can confirm that the DbContext is scoped to the http request only during the lifetime of the MVC execution (maybe MVC is in charge of disposing of the DbContext), so any middleware before or after in the pipeline won't have the same instance of DbContext injected.
I decided then to add a global filter to MVC 6 (because filters are part of MVC framework) so that I can access the same DbContext instance before and after the action's execution.
If anybody is interested on how to create this global filter check:
Entity Framework Core 1.0 unit of work with Asp.Net Core middleware or Mvc filter

Web Api 2 with OWIN OAuth Bearer tokens

I'm in the process of building a web api in visual studio 2013 and want to authenticate using OWIN middleware and bearer tokens. However I already have a database and don't want to use Microsoft's new Identity framework as the majority of tables and columns that it auto generates I simply don't need.
Can anyone point me in the right direction of how to apply this type of authentication without having to use the Microsoft Identity framework?
My suggestion would be to use the framework but extend it to use your objects and infrastructure. I am currently in the middle of doing this and landed on this question. Here's how I've tackled it so far:
Step 1: Your own CustomUserObject
Write/Use your own "ApplicationUser" object. In the template project, you want to modify the "IdentityModels" file. It has ApplicationUser object defined in there. Assuming you already have all the properties from your existing app, you will need to add GenerateUserIdentityAsync() method but change the type of the parameter to UserManager manager). After the change, your method signature looks like this:
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<CustomUserObject> manager)
Step 2: Define your own IUserStore<> implementation
Add a new class CustomUserStore that implements IUserStore, like so:
public class CustomUserStore : IUserStore<CustomUserObject>
{
private readonly IUserManagerService _userManagerService;
public CustomUserStore(IUserManagerService userManagerService)
{
_userManagerService = userManagerService
}
//implementation code for all of the IUserStore methods here using
//userManagerService or your existing services/classes
}
I am using Unity to inject IUserManagementService's implementation above.
I have made use of the comprehensive UserManager class that comes with the Microsoft Identity framework but extended the framework to use my API for authentication and authorization. You could write your own UserManager but I found that it is pretty tedious and there is no reason why UserManager could work for most cases of Securing an app.
Step 3: Changes in the IdentityConfig.cs file
Change the class definition to make ApplicationUserManager class inherit from UserManager
You'll need to do the samething in the constructor of this class as well; i.e. have IUserStore. Modify the Create static method's first line to make use of the new store and a wrapper class that provides as a means to be a "DbContext" like so:
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new ApplicationUserStore(context.Get<UserManagementServiceWrapper>()));
//modify the relevant lines after this to suit your needs
...
}
My UserManagementServiceWrapper looks like this (please note that I'm not too happy that it inherits from a concrete UserManagementService class that provides the methods to connect to the service that provides user data, I'm still building this out):
public class UserManagementServiceWrapper : UserManagementService, IDisposable
{
public void Dispose()
{
throw new NotImplementedException();
}
}
Step 4: Change the ApplicationDbContext class to return a UserManagementServiceWrapper instance
public class ApplicationDbContext : UserManagementServiceWrapper
{
public static UserManagementServiceWrapper Create()
{
return new UserManagementServiceWrapper();
}
}
And that is pretty much it. You still have to write the implementation for CustomUserStore object but everything should work.
Please note this is not boilerplate code and no where near "code review ready", as I said, I'm still digging deeper into this and building it out to use custom stores, data access objects, services etc. I thought you'll get a good start with some of the things that took me a couple of hours to figure out. I will blog about this when I have a good solution.
Hope this helps.
I prob. dont understand the question entirely but it looks like you are trying to do without the whole owin pipeline?
If not then..
You need to implement few interfaces related to users and roles described as below.
http://www.asp.net/identity/overview/extensibility/overview-of-custom-storage-providers-for-aspnet-identity
Have a look at the following post from Scott Allen
http://odetocode.com/blogs/scott/archive/2013/11/25/asp-net-core-identity.aspx
This way you can use your own tables, DAL and services to create UserManager and RoleManager objects.
Edit: Samples over here should give you some pointers.
Edit2: Custom User Store Example.
IRepository is the object which takes care of CRUD.
public class CustomUserStore : IUserStore<User>,....
{
private readonly IRepository _repository;
public CustomUserStore(IRepository repository)
{
if (repository == null)
throw new ArgumentNullException("repository");
_repository = repository;
}
public Task CreateAsync(User user)
{
if (user == null) throw new ArgumentException("user");
_repository.User.Add(user);
return _repository.CommitAsync();
}
...

Get Username of Currently interacting User in WCF both Rest Endpoint and MVC3 with Windows Authentication

In an MVC3 project that I'm working on we're trying to move a lot of our logic that is currently in the controllers into a service layer and expose it as a REST Service in WCF.
So in our Global.asax we create a Service Route like so:
RouteTable.Routes.Add(new ServiceRoute
("Exampleservice", new WebServiceHostFactory(), typeof(ExampleService)));
and our controllers access the service something like this:
public class ExampleController : Controller {
private IExampleService service;
public ExampleController() {
this.service = new ExampleService();
}
public ActionResult Index() {
var results = service.GetAll();
return View(results);
}
}
The main point here being that we use the service class directly (without making requests over the network with an HttpClient).
Our website uses Windows Authentication (it's an intranet site) and we would like to keep it that way. My Question is, is there a way that I can get the User's Identity in the service class that will work both for how we have the Controllers using the service, and the way that WCF uses the service?
For example:
[ServiceContract]
public interface IExampleService
{
[WebGet(UriTemplate = "/")]
List<Results> GetAll();
}
public class ExampleService : IExampleService
{
List<Results> GetAll() {
// Get User Name Here
// In ASP.Net I would use User.Identity.Name
// If I was just worrying about the the REST service I would use
// ServiceSecurityContext.Current.WindowsIdentity.Name
}
}
The instruction suggested by #Ryand.Johnson is correct. The point here is that the controller do not send any credentials to the web service because it run under the asp.net user indentity not the identity of the currently loggedd user. The only way to pass the identity to the proxy is by embedding the call to the web service within an impersonation context this way:
using (WindowsImpersonationContext impersonatedUser = (User.Identity as System.Security.Principal.WindowsIdentity).Impersonate()){
//your proxy call here }
If still this way you get null you have to set manually the default credentials to your proxy
Yes, in the service security context...
OperationContext.Current.ServiceSecurityContext.WindowsIdentity.Name

Resources