Using the LoaderOptimizationAttribute on a WCF service - c#

I have a wcf service that uses the .net System.AddIns framework to load assemblies into a seperate process and app domain. To improve performance I want to enable the Cross-Domain FastPath.
According to the documentation I need to add the LoaderOptimizationAttribute attribute to the main method of my host application. However I do not have a main method as I am using a service.
So is it possible to use the attribute? If not then how can I ensure that the addin assemblies are loaded as domain neutral?
Thanks.

If you are hosting in IIS, you should be gettng "LoaderOptimization(LoaderOptimization.MultiDomainHost)" applied by default, and there seems to be no way to change this that I can find. If you want something else applied, you may need to roll your own host (not that hard for WCF, but certainly not as convenient or feature-rich as IIS hosting).
However, this should load all assemblies as domain-neutral - so it is probably what you want already. Make sure you are not using Assembly.LoadFrom(), as this makes it impossible for appdomains to share the JITed code.

Related

WCF another best practice?

Ok so I have built my WCF service and its functioning great! However, I am starting to implement it into our pre-existing piece of software now and I am instantly running into the question, do I only use the proxy generated code and get rid of the dll that I used initially? Or do I keep both, and make distinctions between the two very obvious?
What I mean by keeping distinctions is, having a ServerUser and a LocalUser property that represent the same user object. However, my LocalUser property would be filled via the dll that the app initally ran with, if the application service is unavailable.
My main reasoning for this thought pattern is that if I remove my dll, I have a single point of failure. If for some reason my ServiceHost is just not up and running, but the DB server is, I would want my users to still be able to do their job. The features that the new WCF implementation utilize are not dependant for employees to do their job. It is more of a convenience in what the WCF service provides. Also, building in this kind of logic to the Service would allow service modifications more readily available in a non IIS hosted environment.
Also, is there a way to build in logic on the service so that when I pull down the proxy code for the client that it just knows to access the DB manually if the ServiceHost is unavailable? If this was a possibility, I think about 90% of all my problems would disappear.
Thank you in advance!
From what you describe it sounds like keeping your existing DLL, i.e. direct access to the DB, would best suit your needs. Having a WCF service adds nothing if, when it fails, you'll just use the DLL anyway.
Ideally you would go with the WCF service completly and offer some kind of redundency to deal with any potenial service issues. Plus, using a service will mean you won't have to deal with any DLL upgrades/deployments.
But, from your question, it sounds like there would be some real issues to deal with should the service not be available, so just do with the DLL.
EDIT: Just read the last part of your question and I don't think that is possible. The proxy code for accessing services is generated when you add the reference to your project. The kind of "dynamic" information you're after would actually require a service.
EDIT: As a follow up to my comment below you could test this by creating a DLL and class, lets call it Class1. Then create a WCF service with a method that will return Class1. Create a client application and add a reference to the service. If you look at the proxy-generated code you should see (hopefully...I'm thinking of this as I type :)) that the method returns Class1, but when you compile it won't be able to find Class1. This is because Class1 does not have the DataContractAttribute which would auto-generate Class1 on the client. So, you have to distribute the shared DLL to the client. Now when the method returns and WCF tries to re-create Class1 it will use the local version in the shared DLL. Your other DLL, which will already be on the client, would use the same shared DLL.

Dynamic Assembly Resolution/Management

Short Version
I have an application which utilizes a plug-in infrastructure. The plug-ins have configurable properties that help them know how to do their job. The plug-ins are grouped into profiles to define how to complete a task, and the profiles are stored in XML files serialized by the DataContractSerializer. The problem is when reading the configuration files, the application deserializing has to have knowledge of all of the plug-ins defined in the configuration file. I'm looking for a way to handle the resolution of unknown plug-ins. See the proposed solution section below for a couple of the ideas I've looked into implementing, but I am open to just about anything (though I'd rather not have to reinvent the application).
Detail
Background
I've developed a sort of Business Process Automation System for internal use for the company I'm currently working for in C# 4. It makes exhaustive use of 'plug-ins' to define everything (from the tasks that are to be performed to the definition of units of work) and relies heavily on a dynamic configuration model which in turn relies on C# 4/DLR dynamic objects to fulfill jobs. It's a little heavy while executing because of its dynamic nature but it works consistently and performs well enough for our needs.
It includes a WinForms configuration UI that uses Reflection extensively to determine the configurable properties/fields of the plug-ins, as well as, the properties/fields that define each unit of work to be processed. The UI is also built on top of the BPA engine so it has a thorough understanding of the (loose) object model put in place that allows the engine to do its job, which, coincidentally, has led to several user experience improvements, such as, ad-hoc job execution and configure-time validation of user input. Again there is room for improvement, however, it seems to do its job.
The configuration UI utilizes the DataContractSerializer to serialize/deserialize the settings specified, so any plug-ins referenced by the configuration must be loaded before (or at the time of) configuration load.
Structure
The BPA engine is implemented as a shared assembly (DLL) which is referenced by the BPA service (a Windows Service), the Configuration UI (WinForms app), and a plug-in tester (Console application version of the Windows Service). Each of the three applications that reference the shared assembly only include the minimum amount of code necessary to perform their specific purpose. Additionally, all plug-ins must reference a very thin assembly which basically just defines the interface(s) that the plugin must implement.
Problem
Because of the extensibility model used in the application, there has always been a requirement that the config UI is run from the same directory (on the same PC) as the Service application. That way the UI always knows about all of the assemblies that the Service knows about so they can be deserialized without running into missing assemblies. Now that we are getting close to roll out of the system, a demand to allow the Configuration UI remotely on any PC in our network has come about from our network admins for security purposes. Typically this wouldn't be a problem if there was always a known set of assemblies to deploy, however, with the ability to extend the application using user built assemblies, there has to be a way to resolve the assemblies from which the plug-ins can be instantiated/used.
Proposed (potentially obvious) Solution
Add a WCF service to the Service application to allow the typical CRUD operations against the configurations which that instance of the service is aware of and rework the configuration UI to act more like SSMS with a Connect/Disconnect model. This doesn't really solve the problem so we would also need to expose some sort of ServiceContract from the Service application to allow querying of the assemblies it knows about/has access to. That's fine and fairly straight forward however the question arises, "When should the UI find out about the assemblies that the Service is aware of?" On connect we could send all of the assemblies from the Service to the UI to ensure that it always knows about all of the assemblies the service does but that gets messy with AppDomain management (potentially unnecessarily) and assembly version conflicts. So I suggested hooking into the AppDomain.AssemblyResolve/AppDomain.TypeResolve events to only download the assemblies that the client isn't aware of yet and only as needed. This doesn't necessarily cleanup the AppDomain management issues but it definitely helps address the version conflicts and related issues.
Question
If you've stuck with me this long I applaud and thank you, but now I'm finally getting to the actual question here. After months of research and finally coming to a conclusion I am wondering if anyone here has had to deal with a similar issue and how you dealt with the pitfalls and shortcomings? Is there a standard way of handling this that I have missed completely, or do you have any recommendations based on how you have seen this successfully handled in the past? Do you see any problems with the proposed approaches or can you offer an alternative?
I'm aware that not everyone lives in my head so please let me know if you need further clarification/explanation. Thanks!
Update
I've given MEF a fair shake and feel that it is too simplistic for my purposes. It's not that it couldn't be bent to handle the plug-in requirements of my application, the problem is doing so would be too cumbersome and dirty to make it feasible. It is a nice suggestion and it has a lot of potential, but in its current state it just isn't there yet.
Any other ideas or feedback on my proposed solutions?
Update
I don't know if the issue I'm encountering is just too localized, if I failed to properly describe what I am trying to achieve, or if this question is just too unreasonably long to be read in its entirety; but the few answers I've received have been subtly helpful enough to help me think through the problem differently and identify some shortcomings in what I am after.
In short, what I'm trying to do is take three applications which in their current state share information (configuration/assemblies) using a common directory structure, and try to make those applications work across a network with minimal impact on usability and architecture.
File shares seem like the obvious answer to this problem (as #SimonMourier proposed in the comments), but using them translates into lack of control and debugability when something goes wrong. I can see them as a viable short term solution, but long term they just don't seem feasible.
tl;dr, but I'm 90% sure you should take a look into MEF.
When I first saw it I was like "aah, another acronym", but you'll see it's very simple, and it's built in into .NET 4. Best of all, it even runs seamlessly on mono and it's a matter of less than an hour (including coffee break) between hearing about it and compiling hello worlds to get used with the features. It's really that simple.
Basically, you "export" something in an assembly and "import" it into another (all via simple attribute decorations), and you choose where to search for it (example, on the applications directory, plug-ins folder, etc).
Edit: what if you try to download and load (and possibly cache) plugins on-the-fly on configuration load?
I think that you could be overlooking a relatively simple solution that derives somewhat from the Microsoft web.config approach:
Have two sections in the config file:
Section 1 contains enough information about the plugin (i.e. name, version) to allow you to load it into an app domain.
Section 2 contains the information serialized by the plugin.
On loading the plugin, pass the information in section 2 and let the plugin deserialize it according to its needs.
Maybe you can divide this problem into two
administrator allow users to download one of predefined configuration (set of libraries) and MEF helps to inject required dependencies
each activity from user should pass through security proxy, plugin modules not allowed call BL directly. Proxy could match custom security attribute and allowed activities.
i.e.
[MyRole(Name = new[] { "Security.Action" })]
void BlockAccount(string accountId){}
[MyRole(Name = new[] { "Manager.Action" })]
void CreateAccount(string userName){}
[MyRole(Name = new[] { "Security.View", "Manager.View" })]
List<> AcountList(Predicate p){}
and allow for AD groups (some abstract description)
corp\securityOperators = "Security.*" //allow calls to all security manipulation
corp\HQmanager = "Manager.View" //allow only view access
corp\Operator = "Manager.*"
I'm not sure I completely understand the problem but I think this situation calls for "type-preserving serialization" - that is, the serialized file contains enough type information to deserialize back to the original object graph without any hints from the calling application as to what types are involved.
I've used Json.NET to do this and I can highly recommend the library for type-preserving serialization of object graphs. It looks like the NetDataContractSerializer can also do this, from the MSDN Remarks
The NetDataContractSerializer differs from the DataContractSerializer in one important way: the NetDataContractSerializer includes CLR type information in the serialized XML, whereas the DataContractSerializer does not. Therefore, the NetDataContractSerializer can be used only if both the serializing and deserializing ends share the same CLR types.
I chose Json.NET because it can serialize POCOs without any special attributes or interfaces. Both Json.NET and the NetDataContractSerializer allow you to use a custom SerializationBinder - in here you could put any logic regarding loading assemblies that may not yet be loaded.
Unfortunately, changing serialization schemes might be the "breaking-est" change to suggest because all your existing files will become incompatible. You might be able to write a conversion utility that deserializes a file using the old method and serializes the resulting object graph using the new method.

Propagate Application Service as WCF Service

I have description of my Application Services using my fancy classes (ServiceDescription class that contains collection of ServiceMethod description, for simplification).
Now, I want to expose one Application Service as one WCF Service (one Contract). The current solution is very lame - I have console application that generates *.svc file for each Application Service (ServiceDescription). There is one method (Operation) generated for one ServiceMethod.
This works well but I would like to make it better. It could be improved using T4 template but I'm sure that there is still better way in WCF.
I would still like to have one *.svc file per one Application Service but I don't want to generate methods (for corresponding Application Service methods).
I'm sure that there must be some interfaces that allow to discover operations dynamically, at runtime. Maybe IContractBehavior...
Thanks.
EDIT1:
I don't want to use generic operation contract because I would like to have the ability to generate service proxy with all operations.
I'm sure that if I write WCF service and operations by hand then WCF uses reflection to discover the operations in the service.
Now, I would like to customize this point in order not to use reflection, just use my "operations discovering code" instead.
I think there is nothing wrong with static code generation in that case. In my opinion, it is a better solution than dynamic generation of contracts. Keep in mind that your contract is the only evidence you have/provide that a service is hosting a particular set operations.
The main issue I see about the dynamic approach is about versioning and compatibility. If everything is dynamically generated, you may end up transparently pushing breaking changes into the system and create some problems with existing clients.
If you have a code generator when you plan on implementing some changes in the application services, it will be easier to remember that the changes you make on the services may have a huge impact.
But if you really want to dynamically handle messages, you could use a generic operation contract (with the Action property set to *), and manually route the messages to the application services.
Keep in mind that you would lose the ability to generate from the service a proxy containing a list of operations available.

Using [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Windows")] To expose Internal properties

Ok so I had a qustion awhile back regarding Silverlight 4 Data Binding with anonymous types, one of the answers was to use [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Windows")] in your AssemblyInfo.cs file.
I tried this and it works!
I know I'm making all my internal properties classes and methods visible to the System.Windows Assembley.
But what kind of risk is this with the following in mind:
The product is a hosted silverlight based web application, so it wont be distributed.
Thanks in advance
Well, actually it will be distributed to every client that accesses it, but that is not the point.
Information hiding is primarily a API design concern. If allowing a framework assembly to peek into your assemblies in order to facilitate your development I see no problems with it.
No one is going to be able to backdoor you if that is what you are worried about.

WCF IIS hosting issue

I am using VSTS2008 + C# + .Net 3.5 to develop a WCF service hosted in IIS 7.0/6.0. I am learning from the following MSDN link,
http://msdn.microsoft.com/en-us/library/ms733766.aspx
My question is, suppose I implement the WCF service inside a class library and compiled into some specific DLL assembly. In the service svc file, seems there is no way to specify the assembly, in the MSDN sample, only full (including namespace) class name is specified. So, how did WCF runtime finds the assembly which contains the actual implementation of the DLL assembly at server side? Even if I put the assembly into bin sub-folder of the virtual directory, and if there are many DLLs in bin sub-directory, how did WCF runtime knows which dll contains the actual implementation for the specific WCF service?
Marc is correct about putting the assembly name after the namespace with a comma to separate it: I can confirm that it worked for my own WCF service when I did that. The "dll" extension was not required.
So it sounds like your error 404.3 is due to something other than that. I'm sure I've had that one before, though I'm unable to reproduce it when I try to now. But I have a feeling it had something to do with the permissions on the folder in IIS - perhaps check to see if opening up the permissions more will fix the problem. I think the relevant users would be the IIS_IUSRS on your own machine, and maybe also other processes like NETWORK SERVICE (though I could be wrong on this).
The other thing that springs to mind is encryption; I found that when my web folders were encrypted (with the standard Vista encryption) they couldn't be accessed properly by IIS and would give errors like this. So if you have encryption on those files/folders, maybe try turning it off.
(not working - I've left this here simply for visibility so other SO users can see what didn't work)
I'd need to check, but I'm fairly certain it follows the usual pattern - so you could also have written "Some.Namespace.Service, Some.Assembly.dll" (or if that fails, try it omitting the .dll from the end).
I seem to recall that there is one minor change to normal here... usually the runtime will respect [assembly:TypeForwardedTo(...)], but I don't think that WCF handles this - but otherwise, standard type/dll strings should work.

Categories

Resources