How to configure AutoMapper 9.0 in IIS hosted WCF application - wcf

I want to use AutoMapper 9.0 in a WCF project containing several services that will be hosted in IIS. I've only found one other related SO question but its dealing with a 10 year old version of AutoMapper and is not asking the same question. Its answer is similar to the top hits on Google which suggest using a ServiceBehavior but that doesn't seem applicable when I want multiple services to use the same mapper. The defense rests.
In a web project, you might create a static MapperConfiguration in the Global.asax when the application starts, but WCF doesn't have a Global.asax. It looks like there are a few options for executing initialization code in WCF:
Include an AppInitialize() method in the App_Code folder. This will be dynamically compiled at runtime and people have complained that it can have missing reference issues in IIS so I'm not confident AutoMapper or its dependencies will be found once deployed to IIS.
Create a custom ServiceHost. This seems like it would execute once when the application starts, but also looks like it ignores the web.config configuration, which I don't want.
Use the Configure method per service. This has the same drawback as #2 and also I become concerned with thread safety (as in the ServiceBehavior approach) since two services could try to initialize the MapperConfiguration at once.
I considered just creating a class with a static property that would create a static MapperConfiguration or IMapper instance if it was not already created, but as in #3, I'm worried this may not be thread safe. Maybe if I did something like this?
public static class MapperConfig
{
private static IMapper _modelMapper;
private static readonly object _mapperLocker = new object();
public static IMapper ModelMapper
{
get
{
lock(_mapperLocker)
{
if (_modelMapper == null)
{
var config = new MapperConfiguration(cfg => cfg.AddProfile(new MappingProfile1()));
_modelMapper = config.CreateMapper();
}
}
return _modelMapper;
}
}
}
Where two services may call ModelMapper simultaneously. Another downside of this is the first request to any service will have to wait for the mapping to compile, but I'm not sure I can get away from that. I definitely don't want it compiling the mappings per call and would prefer not to even have to do it per service. Can you advise on the thread safety of MapperConfiguration and the best way to use it in IIS-hosted WCF?

Related

Autofac Multitenant Database Configuration

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...

WCF Proxy Pool/Manager

My application needs to comunicate with several external WCF services to satisfy requests from client applications. Being itself a WCF service, it must of course be able to process several simultaneous requests. That being, and since I will be acessing more than one service, I thought about grouping clients in the following manner:
public static class ClientManager
{
private static readonly Service1Client _service1Client = new Service1Client();
private static readonly Service2Client _service2Client = new Service2Client();
...
public static Service1Client Service1DefaultClient { get { return _service1Client; } }
public static Service2Client Service2DefaultClient { get { return _service2Client; } }
}
Then, from the remaining of the code, I would only need to execute
ClientManager.Service1DefaultClient.SomeMethod();
ClientManager.Service2DefaultClient.SomeMethod();
...
The idea is to create a central place to better manage WCF clients. However, I don't really know if this design is the most appropriate one for a service which will be issuing several requests at the same time to Service1DefaultClient and Service2DefaultClient. What do you suggest? Creating a more complex client pool with several proxies from each service to choose from?
Having static client proxies doesn't look like a good idea to me.
If ClientBase instance transitions to the Faulted state, it becomes unusable and you have to re-create it.
If you have a stateful service, session lifetime will be the same as lifetime of a client proxy object, which is very long in your case.
Depending on your binding settings, ClientBase may serialize concurrent calls made on the same proxy instance. In your case, this may strongly affect performance.
I just don't see what problem does this solve.
Proxies are relatively lightweight because of the ChannelFactory caching, so I would just create a new instance every time it is needed.

Using MEF in Service layer (WCF)

So far I found that MEF is going well with presentation layer with following benefits.
a. DI (Dependency Injection)
b. Third party extensibility (Note that all parties involved should use MEF or need wrappers)
c. Auto discovery of Parts (Extensions)
d. MEF allows tagging extensions with additional metadata which facilitates rich querying and filtering
e. Can be used to resolve Versioning issues together with “DLR and c# dynamic references” or “type embedding”
Pls correct me if I’m wrong.
I'm doing the research on whether to use MEF in Service layer with WCF. Pls share your experience using these two together and how MEF is helping you?
Thanks,
Nils
Update
Here is what my result of research so far. Thanks to Matthew for helping in it.
MEF for the Core Services - cost of changes are not justifying the benefits. Also this is big decision and may affect the service layer in good or bad way so needs lot of study. MEF V2 (Waiting for stable version) might be better in this case but little worried about using MEF V1 here.
MEF for the Function service performs - MEF might add the value but it’s very specific to the service function. We need to go deep into requirement of service to take that decision.
Study is ongoing process, so everyone please share your thoughts and experience.
I think any situation that would benefit from separation-of-concerns, would benefit from IoC. The problem you face here is how you require MEF to be used within your service. Would it be for the core service itself, or some function the service performs.
As an example, if you want to inject services into your WCF services, you could use something similar to the MEF for WCF example on CodePlex. I haven't looked too much into it, but essentially it wraps the service location via an IInstanceProvider, allowing you to customise how your service type is created. Not sure if it supports constructor injection (which would be my preference) though...?
If the WCF service component isn't where you want to use MEF, you can still take advantage of MEF for creating subsets of components used by the service. Recently for the company I work for, we've been rebuilding our Quotation process, and I've built a flexible workflow calculation model, whereby the workflow units are MEF composed parts which can be plugged in where needed. The important part here would be managing how your CompositionContainer is used in relation to the lifetime of your WCF service (e.g. Singleton behaviour, etc.). This is quite important if you decide to create a new container each time (container creation is quite cheap, whereas catalog creation can be expensive).
Hope that helps.
I'm working on a solution where the MEF parts that I want to use across WCF calls are stored in a singleton at the application level. This is all hosted in IIS. The services are decorated to be compatible with asp.net.
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
In Global.asax, I import the parts.
[ImportMany(typeof(IOption))]
public IEnumerable<IOption> AvailableOptions{ get; set; }
After initializing the catalog and container, I copy the imported objects to my singleton class.
container.ComposeParts(this);
foreach (var option in AvailableOptions)
OptionRegistry.AddOption(option);
EDIT:
My registry class:
public static class OptionRegistry
{
private static List<IOption> _availableOptions= new List<IOption>();
public static void AddOption(IOption option)
{
if(!_availableOptions.Contains(option))
_availableOptions.Add(option);
}
public static List<IOption> GetOptions()
{
return _availableOptions;
}
}
This works but I want to make it thread safe so I'll post that version once it's done.
Thread-safe Registry:
public sealed class OptionRegistry
{
private List<IOptionDescription> _availableOptions;
static readonly OptionRegistry _instance = new OptionRegistry();
public static OptionRegistry Instance
{
get { return _instance; }
}
private OptionRegistry()
{
_availableOptions = new List<IOptionDescription>();
}
public void AddOption(IOptionDescription option)
{
lock(_availableOptions)
{
if(!_availableOptions.Contains(option))
_availableOptions.Add(option);
}
}
public List<IOptionDescription> GetOptions()
{
return _availableOptions;
}
}
A little while ago i was wondering how I could create a WCF web service that will get all of its dependencies wired by MEF but that i wouldnt need to write a single line of that wire up code inside my service class.
I also wanted it to be completely configuration based so i could just take my generic solution to the next project without having to make code changes.
Another requirement i had was that i should be able to unit-test the service and mock out its different dependencies in an easy way.
I came up with a solution that ive blogged about here: Unit Testing, WCF and MEF
Hopefully will help people trying to do the same thing.

what is the global.asax Application_Start equivalent when using WAS in IIS7

I'd like to use the netTcpBinding for my WCF application which is currently hosted in IIS7, which means configuring it to use WAS instead. This is fairly straight forward however, my application previously made use of the Application_Start event in the global.asax file. I do not require access to the httpContext(which I understand access has been removed in IIS7), however I would still like to hook into the start or init methods?
Does an equivalent exist when hosting an application in WAS as apposed to IIS7?
Using classic mode is not an option(again I'm not interested in the httpcontext and this only appears to work if using an http binding) - and I've seen an example of putting a static class instide the app_code folder which looks like a horrible hack.
I believe AppInitialize() is the method you're looking for. Here's an article on using it to initialise Castle Windsor in a WAS hosted WCF service:
Castle Windsor and non-HTTP Protocol WCF Services
The essence of the article is, instead of using Application_Start() which won't get called in WAS:
protected void Application_Start(object sender, EventArgs e)
{
var container = new WindsorContainer("ioc.config");
DefaultServiceHostFactory.RegisterContainer(container.Kernel);
}
Use:
public class InitialiseService
{
/// <summary>
/// Application initialisation method where we register our IOC container.
/// </summary>
public static void AppInitialize()
{
var container = new WindsorContainer("ioc.config");
DefaultServiceHostFactory.RegisterContainer(container.Kernel);
}
}
To quote Matt:
I confess I spent a while looking at the Host Factory in more detail,
looking to wrap the DefaultServiceHostFactory. However, there appears
to be a far simpler solution and that is to make use of the little
documented AppInitialize method. If you create a class (any class),
put it into the ASP.NET App_Code folder in your project and give it a
method signature as defined below, this little baby will get fired
exactly when you want it to. You can then initialise your IoC
container in there.
AppInitialize is a valid method of initializing your service. But there are some other methods that might work better for you and they are described in this article: How to Initialize Hosted WCF Services
NOTE: the original link went away. The link above is to a copy on archive.org.

WCF, SubSonic SimpleRepository and multithreading

I'm currently in the process of writing a WCF REST service with SubSonic SimpleRepository and the WCF REST Contrib library. The service is going to be hosted on IIS 7. The database is going to be MS SQL Server. I could not really find a good example which is using this combination of technologies on the internet. The service should expose a database in a RESTful manner but also contains some business rules (e.g. registering users, saving statistics) so I can't use ADO.net Data Services. Because there are going to be a lot of clients accessing the service at the same time it's important that the service can serve several clients at the same time.
For good performance I want to use the following service behaviour:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession, ConcurrencyMode=ConcurrencyMode.Multiple)]
There are no instance variables in the Service class and as I understand it, those attribute values cause new a instance of the service class to be created for every call (not per session because it is called over https).
I used the following simple class for creating the SimpleRepository once (singleton):
public class DB
{
private static SimpleRepository _Repository;
public static SimpleRepository Repository
{
get
{
if (_Repository == null)
{
_Repository = new SimpleRepository("5Drive", SimpleRepositoryOptions.RunMigrations);
}
return _Repository;
}
}
}
Here is an example method of my service:
Interface:
[OperationContract]
[WebGet(UriTemplate = "vehicles")]
[WebDispatchFormatter]
Vehicles GetVehicles();
Implementation:
public Vehicles GetVehicles()
{
// get all vehicles for the logged in user
var vehicles = from v in DB.Repository.All<Vehicle>()
where v.UserID == GetUserID()
orderby v.Name
select v;
return new Vehicles(vehicles);
}
So, here is my question: can I do it this way? Is SimpleRepository thread-safe? Do I have to create a SimpleRepository in every method instead of using a singleton? What about performance when I do that? I looked at the SimpleRepository source code and I think that the migration code is not thread safe because the "private readonly List migrated;" is not synchronized but I might be wrong.
Maybe I'm missing something and I can just ignore multi-threading and configure IIS differently?
Thanks for your help!