I'm using custom asp.net membership provider with underlaying nhibernate data access code, which is fine. Now I need to exercise these methods using tests.
Anyone interested in suggesting how these methods should be tested? with providing some links explaining test methods using some standars maybe ?
This is my first question so be gentle :)
When it comes to unit testing any code that does something with the database or a 3rd party library you should de-couple these dependencies so that your tests only test your code.
For example, if we have a method in our membership provider for adding a single user, what we want to be testing is that our code for this single method works correctly and not that the database is up and running or that methods called by this method work. Our unit test should still pass even if the database is offline or if method calls on other classes fail.
This is where Mocking comes into play. You'll want to mock out your data context and set up any methods you'll be using on it so that you can control its response.
Look closely at the methods you have in your membership provider. What should each one do? That's the only thing you really want to test. Does this method, as a standalone unit, do the job I'm expecting it to.
Membership providers are pretty difficult to mock and test, so personally I don't bother. What I do however is place all my membership code in classes that are easily testable.
Most of my custom providers look something like this:
public class CustomMembershipProvider : MembershipProvider
{
private readonly IUserService _userService;
public ButlinsMembershipProvider()
{
_userService = DI.Resolve<IUserService>();
}
public override bool ValidateUser(string username, string password)
{
return _userService.Authenticate(username, password);
}
}
In this example, I would write integration tests to verify the behavior of the user service. I don't test the provider.
Related
With Elsa workflow designer possible to define a workflow and publish it, also can make a workflow programmatically by implementing the IWorkflow interface.
I need to make programmatically workflow at runtime, save it on the database and run it sometimes.
in the asp.net core project controller, I resolve IWorkflowBuilder as a dependency and make a workflow with WorkflowBuilder and return a WorkFlowblueprint object, but I don't know how I can store it and how to run it?
I also have Elsa dashboard on my project and I use EntityFramework Persistence for it.
Is there a way to convert a WorkflowBluePrint to WorkFlowDefination or generate WorkflowDefination from scratch programmatically?
Does everyone have any idea?
Although it might theoretically be possible to store an IWorkflow implementation in the database, there are some caveats that make this tricky to say the least. Here is why:
A workflow definition created by the designer consists purely of a list of activities and connections between them. Because of that, everything is easily serialized into JSON and stored in the database.
However, when you write a C# class, you can do more fancy things, such as configuring activities using C# lambda expressions and implement "inline" activity code. When you try to serialize this to JSON, these C# expressions will be serialized using just their type names.
Although there might be ways to somehow store a programmatic workflow into the database, perhaps even by storing a compiled assembly in the DB, I don't think it's worth the trouble because there are better ways.
You said that you need a programmatic workflow that you only run sometimes.
To achieve that, you do not need to store a workflow in the database.
The way Elsa works is that all workflow sources are converted into a thing called a Workflow Blueprint.
A workflow blueprint is what represents an executable workflow where all the necessary details are dehydrated that the workflow invoker can use.
There are different "sources" to establish these workflow blueprints by means of classes that implement IWorkflowProvider, of which there are three:
Programmatic Workflow Provider
Database Workflow Provider
Blob Storage Workflow Provider
The programmatic provider is what turns IWorkflow implementations into workflow blueprints, while the database provider turns workflow definitions into blueprints. The blob storage provider is similar, except it turns JSON files into blueprints.
The bottom line is that the origin of a workflow blueprint doesn't matter for the workflow engine.
All workflow blueprints are accessed through a service called the workflow registry, which you can use to load & execute a given workflow.
For example, if you have a programmatic workflow called MyWorkflow, you can execute it whenever you want like this:
public class MyWorkflow : IWorkflow
{
public void Build(IWorkflowBuilder builder)
{
builder.WriteLine("Hello World!");
}
}
[ApiController]
[Route("my-workflow")]
public class MyWorkflowController : Controller
{
private readonly IWorkflowRegistry _workflowRegistry;
private readonly IStartsWorkflow _workflowStarter;
public MyWorkflowController(IWorkflowRegistry workflowRegistry, IStartsWorkflow workflowStarter)
{
_workflowRegistry = workflowRegistry;
_workflowStarter = workflowStarter;
}
[HttpGet("run")]
public async Task<IActionResult> RunMyWorkflow(CancellationToken cancellationToken)
{
// 1. Get my workflow blueprint.
var myWorkflowBlueprint = (await _workflowRegistry.GetWorkflowAsync<MyWorkflow>(cancellationToken))!;
// 2. Run the workflow.
await _workflowStarter.StartWorkflowAsync(myWorkflowBlueprint, cancellationToken: cancellationToken);
return Ok();
}
}
Invoking this controller will execute MyWorkflow.
As you can see, there is no need to store the workflow in the database in order to be able to execute it on demand. Even if you did store the workflow in the database, the code would be the same, provided that the name of the workflow remains "MyWorkflow". Under the covers, the GetWorkflowAsync<TWorkflow> is simply an extension method that uses the type name to find the workflow by name. If you wanted to load a workflow by name for which there's no workflow class defined, you would simply use FindByNameAsync, or FindAsync if all you had is a workflow definition ID.
I'm currently making a library that interacts with a particular API that requires an oAuth OIDC connection/token and I'd like to make something that makes that particular part easier for users of this library so they don't need all this custom code.
What is this currently called and is there an example of code?
I ask because from trying to get this work, the documentation is ALL OVER THE PLACE. It looks like this particular process has undergone significant changes multiple times as things went on from before netcore to netcore2 and now netcore31.
Both AddAuthentication and AddOpenIdConnect are extension methods.
An extension method allows you to "add" methods to a type without having to modify the type directly - the methods aren't actually added to the type, but we can call them as if they had been. This is useful in situations where you'd like to extend the behaviour of a class created by a third party but don't have access to the source code.
As for what the particular pattern in question is, whilst there is no canonical name, it's merely a way of encapsulating the configuration of services and dependencies for your application.
AddAuthentication is an extension method of IServiceCollection, which is services type. AddAuthentication has a return type of AuthenticationBuilder, and AddOpenIdConnect is an extension method for AuthenticationBuilder. This is the implementation of AddOpenIdConnect, but as you're looking to encapsulate the configuration, you could probably do something like this:
public static class OpenIdConnectExtensions
{
public static AuthenticationBuilder ConfigureOpendIdConnect(
this AuthenticationBuilder builder)
{
return builder.AddOpenIdConnect(options =>
{
options.SignInScheme = IdentityConstants.ExternalScheme;
// Do whatever else you need.
});
}
}
And call it as follows:
services
.AddAuthentication()
.ConfigureOpendIdConnect()
Middleware, on the other hand, is code that executes as part of a pipeline in order to process requests and responses. The middleware sits in the middle of receiving requests and sending responses, hence the name. This allows you do things such as always adding certain headers to responses without that logic being split across your application. As you correctly mentioned, you see these being applied via calls such as app.UseXyz().
I have a base abstract context which has a couple hundred shared objects, and then 2 "implementation" contexts which both inherit from the base and are designed to be used by different tenants in a .net core application. A tenant object is injected into the constructor for OnConfiguring to pick up which connection string to use.
public abstract class BaseContext : DbContext
{
protected readonly AppTenant Tenant;
protected BaseContext (AppTenant tenant)
{
Tenant = tenant;
}
}
public TenantOneContext : BaseContext
{
public TenantOneContext(AppTenant tenant)
: base(tenant)
{
}
}
In startup.cs, I register the DbContexts like this:
services.AddDbContext<TenantOneContext>();
services.AddDbContext<TenantTwoContext>();
Then using the autofac container and th Multitenant package, I register tenant specific contexts like this:
IContainer container = builder.Build();
MultitenantContainer mtc = new MultitenantContainer(container.Resolve<ITenantIdentificationStrategy>(), container);
mtc.ConfigureTenant("1", config =>
{
config.RegisterType<TenantOneContext>().AsSelf().As<BaseContext>();
});
mtc.ConfigureTenant("2", config =>
{
config.RegisterType<TenantTwoContext>().AsSelf().As<BaseContext>();
});
Startup.ApplicationContainer = mtc;
return new AutofacServiceProvider(mtc);
My service layers are designed around the BaseContext being injected for reuse where possible, and then services which require specific functionality use the TenantContexts.
public BusinessService
{
private readonly BaseContext _baseContext;
public BusinessService(BaseContext context)
{
_baseContext = context;
}
}
In the above service at runtime, I get an exception "No constructors on type 'BaseContext' can be found with the constructor finder 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder'". I'm not sure why this is broken....the AppTenant is definitely created as I can inject it other places successfully. I can make it work if I add an extra registration:
builder.RegisterType<TenantOneContext>().AsSelf().As<BaseContext>();
I don't understand why the above registration is required for the tenant container registrations to work. This seems broken to me; in structuremap (Saaskit) I was able to do this without adding an extra registration, and I assumed using the built in AddDbContext registrations would take care of creating a default registration for the containers to overwrite. Am I missing something here or is this possibly a bug in the multitenat functionality of autofac?
UPDATE:
Here is fully runable repo of the question: https://github.com/danjohnso/testapp
Why is line 66 of Startup.cs needed if I have lines 53/54 and lines 82-90?
As I expected your problem has nothing to do with multitenancy as such. You've implemented it almost entirely correctly, and you're right, you do not need that additional registration, and, btw, these two (below) too because you register them in tenant's scopes a bit later:
services.AddDbContext<TenantOneContext>();
services.AddDbContext<TenantTwoContext>();
So, you've made only one very small but very important mistake in TenantIdentitifcationStrategy implementation. Let's walk through how you create container - this is mainly for other people who may run into this problem as well. I'll mention only relevant parts.
First, TenantIdentitifcationStrategy gets registered in a container along with other stuff. Since there's no explicit specification of lifetime scope it is registered as InstancePerDependency() by default - but that does not really matter as you'll see. Next, "standard" IContainer gets created by autofac's buider.Build(). Next step in this process is to create MultitenantContainer, which takes an instance of ITenantIdentitifcationStrategy. This means that MultitenantContainer and its captive dependency - ITenantIdentitifcationStrategy - will be singletons regardless of how ITenantIdentitifcationStrategy is registered in container. In your case it gets resolved from that standard "root" container in order to manage its dependencies - well, this is what autofac is for anyways. Everything is fine with this approach in general, but this is where your problem actually begins. When autofac resolves this instance it does exactly what it is expected to do - injects all the dependencies into TenantIdentitifcationStrategy's constructor including IHttpContextAccessor. So, right there in the constructor you grab an instance of IHttpContext from that context accessor and store it for using in tenant resolution process - and this is a fatal mistake: there's no http request at this time, and since TenantIdentitifcationStrategy is a singleton it means that there will not ever be one for it! So, it gets null request context for the whole application lifespan. This effectively means that TenantIdentitifcationStrategy will not be able to resolve tenant identifier based on http requests - because it does not actually analyze them. Consequently, MultitenantContainer will not be able to resolve any tenant-specific services.
Now when the problem is clear, its solution is obvious and trivial - just move fetching of request context context = _httpContextAccessor.HttpContext to TryIdentifyTenant() method. It gets called in the proper context and will be able to access request context and analyze it.
PS. This digging has been highly educational for me since I had absolutely no idea about autofac's multi-tenant concept, so thank you very much for such an interesting question! :)
PPS. And one more thing: this question is just a perfect example of how important well prepared example is. You provided very good example. Without it no one would be able to figure out what the problem is since the most important part of it was not presented in the question - and sometimes you just don't know where this part actually is...
I'm moving a Web Api 2 project to MVC 6, since Microsoft is merging the two APIs in ASP.NET 5. In my WebApi project I had a custom Attribute Filter class that would authenticate, authorize and prevent transaction replays using a combination of public key, private key and HMAC authentication (basically, doing this with some tweaks to fit into my project).
Now in MVC6, as far as I understand I must stop using anything in the Microsoft.Web.Http namespace and instead use Microsoft.AspNet.Mvc. So I have done that, but the Microsoft.AspNet.Mvc.Filters doesn't seem to have any equivalent of Web Api 2's IAuthenticationFilter.
This is a problem for me because my customer AuthenticationFilter implemented all of IAuthenticationFilter, with all the logic in there. More importantly, it was using the Context to temporarily store the public key of the account, so my controller could access it to load up the account in turn.
So my question is, what is the proper way to filter requests in MVC6, using an Authentication Filter-like class to intercept the requests and return the appropriate status codes? I can't find any article that goes specifically in these details (they all tend to cover MVC5).
I know it's an older question, but hopefully someone (maybe even yourself) might find value in the answer.
MVC6 does in fact have an alternative. You have an
public abstract class AuthorizationFilterAttribute :
Attribute, IAsyncAuthorizationFilter, IAuthorizationFilter, IOrderedFilter
which basically tells you, that you can create your custom class, derive it from this (namespace of all of these interfaces, btw, is Microsoft.AspNet.Mvc.Filters and that should be it. You can either decorate the action with it, or you can do this in Startup.cs, to apply to all actions:
public void ConfigureServices(IServiceCollection services)
{
// Add MVC services to the services container.
services.AddMvc(options =>
{
// add an instance of the filter, like we used to do it
options.Filters.Add(new MySpecialFilter());
});
services.AddTransient<LogFilter>();
}
If you want to use a bit more logic in the filter (e.g. my LogFilter above) which is instantiated through DI, you need to use either Service Filters or Type Filters.
You can now decorate the actions with [ServiceFilter(typeof(LogFilter))] or use o.Filters.Add(new ServiceFilterAttribute(typeof(LogFilter))); in the Startup.cs file. But keep in mind, to do this you need to register the type with the DI container, like I did above with the .AddTransient<>() call.
IAuthenticationFilter is no more and IAuthorizationFilter simply does not replace it in MVC 6
Reason: authentication is NOT EQUAL to authorization.
Therefore IMO the authentication filter should stay available!
I'm currently working on an MVC4 project, i make use if Ninject to inject a UnitOfWork into my controllers, and I'm using UnitOfWork + Generic Repository pattern.
I don't like VS2012 MVC4 template because it directly uses database access (db initialization, for example).
My project divides in:
a UI project (the mvc4 application), with Forms Authentication
a Domain project (the db entities, the repositories, the UnitOfWork interface plus two UnifOfWork implementations, one with MOQ and one with EF; they are injected into UI controllers via Ninject).
I looked at this example:
http://kevin-junghans.blogspot.it/2013/03/decoupling-simplemembership-from-your.html
related to this question
SimpleMembership - anyone made it n-tier friendly?
And now I have some question:
How can i inject my UoW here? WebSecurity class is static, there is no contructor, it directly instantiate the UoW to perform activities on db ...
I always have to initialize WebMatrix to directly access DB? This piece of code:
public static void Register()
{
Database.SetInitializer<SecurityContext>(new InitSecurityDb());
SecurityContext context = new SecurityContext();
context.Database.Initialize(true);
if (!WebMatrix.WebData.WebSecurity.Initialized)
WebMatrix.WebData.WebSecurity.InitializeDatabaseConnection("DefaultConnection",
"UserProfile", "UserId", "UserName", autoCreateTables: true);
}
breaks my decoupling with the Domain .. how can i make WebSecurity using my UnitOfWork for example? what is the best practice?
How can i store additional data (for example, EmailAddress and so on) and retrieve it, without performing a Database query everytime i have to access the User profile? Something like the old CustomPrincipal ... Custom principal in ASP.NET MVC
Thank you!
You have a lot of questions here Marco. Let me take a stab at them.
How to inject a UOW
Static classes and dependency injection do not mix well, as pointed out in this QA. When I first went through this exercise of decoupling SimpleMembership the concentration was just on decoupling from the domain, as discussed in the article you referenced. It was just a first step and it can be improved on, including making it easier for dependency injection. I debated whether to make WebSecurity static or not and went with static because that is how the original SimpleMembership is implemented, making it a more seamless transition for user of the SimpleSecurity. SimpleSecurity is an open source project and contributions are welcome. Making it non-static would not be difficult and probably makes sense in the long run. Once it is made non-static we could use a Factory pattern to create the UnitOfWork and inject the appropriate Factory.
Why do I have to Register WebSecurity?
SimpleSecurity is just a wrapper around the WebMatrix WebSecurity classes, which require initialization. The Register method just makes sure that WebMatrix is initialized and initializes our database. I disagree that having this method call in the Globa.asax couples it with the Domain in any way. Having it work with your UnitOfWork should have nothing to do with the Application Domain, or with having to call a Register method at application start-up.
How can I store additional data (ex: email) and retrieve it, without performing a database query every time?
This is actually accomplished quite easy in .NET 4.5 by using ClaimsPrincipal. All principals in .NET 4.5 inherit from ClaimsPrincipal, which allows you to store information in the principal as claims. Claims are basically key value pairs that let you store any type of data on the user. For example in ASP.NET the roles for a user are stored as claims. To add your own claims you need to do something called claims transformation. Then to retrieve the information you can create a custom claims principal. Adding this to SimpleSecurity would be a nice feature.