WCF Session Service hosted in ASP.NET MVC 2.0 application - asp.net-mvc

I have a must to host WCF Service using WCF Session mechanism.
I've read http://msdn.microsoft.com/en-us/library/ms733040.aspx but it is not enough...
My simple scenearion:
I have solution with 4 projects.
First - SessionWCF.Base, it is simple Class Library that contains base interface IServiceBase for my service.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace SessionWCF.Base
{
[ServiceContract(SessionMode = SessionMode.Required)]
public interface IServiceBase
{
[OperationContract(IsInitiating = true, IsTerminating = false)]
void BeginSession(string message);
[OperationContract(IsInitiating = false, IsTerminating = false)]
string GetMessage(int number);
[OperationContract(IsInitiating = false, IsTerminating = true)]
void EndSession();
}
}
Second - SessionWCF.Lib, it is WCF Class Library that contains service interface ISessionService and service class SessionService , it has project reference to SessionWCF.Base
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using SessionWCF.Base;
namespace SessionWCF.Lib
{
[ServiceContract(SessionMode = SessionMode.Required)]
public interface ISessionService : IServiceBase
{
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Activation;
namespace SessionWCF.Lib
{
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class SessionService : ISessionService
{
string message = "";
#region ISessionService Members
public void BeginSession(string message)
{
this.message = message;
}
public string GetMessage(int number)
{
return "message: " + message + " number: " + number;
}
public void EndSession()
{
message = "";
}
#endregion
}
}
Third - SessionWCF.Web it is ASP.NET MVC 2.0 application that has inside SessionService.svc file. I've deleted code behind and opened XML editor, this service is pointed to service from SessionWCF.Lib, and of course this project has reference to SessionWCF.Lib.
SessionService.svc:
<%# ServiceHost Language="C#" Debug="true" Service="SessionWCF.Lib.SessionService" CodeBehind="SessionWCF.Lib.SessionService.cs" %>
Web.config:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service behaviorConfiguration="SessionServiceBehavior" name="SessionWCF.Web.SessionService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="largeMessageHttpBinding" contract="SessionWCF.Lib.ISessionService">
<identity>
<dns value="**********"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://**********/SessionWCF/SessionService.svc"/>
</baseAddresses>
</host>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="largeMessageHttpBinding" maxReceivedMessageSize="10485760">
<readerQuotas maxArrayLength="100000"/>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
<behavior name="SessionServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Fourth - SessionWCF.WPF it is standard WPF application that contanins SessionProxy class and in xaml form click event to call web service. This project has project reference to first one SessionWCF.Base.
SessionProxy class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SessionWCF.Base;
using System.ServiceModel;
namespace SessionWCF.WPF
{
public class SessionProxy
{
public IServiceBase Proxy { get; set; }
public SessionProxy(string url)
{
WSHttpBinding binding = new WSHttpBinding();
binding.ReceiveTimeout = new TimeSpan(0, 10, 0);
binding.OpenTimeout = new TimeSpan(0, 1, 0);
ChannelFactory<IServiceBase> factory = new ChannelFactory<IServiceBase>(binding,
new EndpointAddress(url));
Proxy = factory.CreateChannel();
}
}
}
Click event in xaml form:
private void Button_Click(object sender, RoutedEventArgs e)
{
string url = "http://**********/SessionWCF/SessionService.svc";
SessionProxy client = new SessionProxy(url);
client.Proxy.BeginSession("my message");
string msg = client.Proxy.GetMessage(666);
client.Proxy.EndSession();
txtMsg.Text = msg;
}
Now:
When I call web service in web browser I've get following error:
Error in '/SessionWCF' Application.
Contract requires Session, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: Contract requires Session, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[InvalidOperationException: Contract requires Session, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it.]
System.ServiceModel.Description.DispatcherBuilder.BuildChannelListener(StuffPerListenUriInfo stuff, ServiceHostBase serviceHost, Uri listenUri, ListenUriMode listenUriMode, Boolean supportContextSession, IChannelListener& result) +16376242
System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost) +1940
System.ServiceModel.ServiceHostBase.InitializeRuntime() +82
System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +64
System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +789
System.ServiceModel.HostingManager.ActivateService(String normalizedVirtualPath) +287
System.ServiceModel.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath) +1132
[ServiceActivationException: The service '/SessionWCF/SessionService.svc' cannot be activated due to an exception during compilation. The exception message is: Contract requires Session, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it..]
System.Runtime.AsyncResult.End(IAsyncResult result) +890624
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +180062
System.Web.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar) +136
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.1
When I call it in my xaml event I get ServiceActivationException:
The requested service, 'http://**********/SessionWCF/SessionService.svc' could not be activated. See the server's diagnostic trace logs for more information.
Is it wrong configuration in web.config?
Maybe I'm missing something in service attributes?
And the most important. Why it alerts me about BasicHttpBinding when I'm not using it ???
Any one could help me with this please? It is critical to my current project...
Regards,
Daniel Skowroński
UPDATE:
#marc_s
Firstly:
I think that server-side is wrong because when I simply paste url
'http://**********/SessionWCF/SessionService.svc' in any web browser I'll get error
"Contract requires Session, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it. " instead metadata...
Secondly:
In my client WPF application I have always two options:
First - Create service reference and IDE will automatically generate proxy class and add all configuration to app.config.
Here I can't do that because I'm getting the same error as in web browser when I point to web service in Service Reference designer.
Second - Create poxy manually and app binding configuration from code, this gives me opportunity create proxy step by step, but it seems that ServiceActivationException it is the same problem "ACTIVATION", you can see in stack trace this lines:
[ServiceActivationException: The service '/SessionWCF/SessionService.svc' cannot be activated due to an exception during compilation. The exception message is: Contract requires Session, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it..]
System.Runtime.AsyncResult.End(IAsyncResult result) +890624
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +180062
System.Web.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar) +136
Regards,
Daniel Skowroński
UPDATE:
#marc_s
I don't this it is the case because:
Firstly:
<services>
<service name="SessionWCF.Web.SessionService"
behaviorConfiguration="SessionServiceBehavior">
Service name it is a name of web service file inside asp.net application, so it points to SessionService.svc which belongs to SessionWCF.Web assembly (the same name as project).
Secondly:
<%# ServiceHost Language="C#" Debug="true"
Service="SessionWCF.Lib.SessionService"
CodeBehind="SessionWCF.Lib.SessionService.cs" %>
Service= is a factory method that gets "type" of the service to create, it also needs class description so CodeBehind= must be pointed to SessionService.cs file where factory method can find SessionService type inside SessionWCF.Lib assembly.
Mentioned two statements are not the issue because when NOT using State Service scenario this works like a charm...
I believe that for the State Service it must me configure something more in web.config are I'm missing something in interface/class description in WCF Class Library...
I'm still in critical situation...
Regards,
Daniel Skowroński
UPDATE
#marc_s you wrote
I think you're wrong here on the SVC
file - check out:
msdn.microsoft.com/en-us/library/aa751792.aspx
- the Service=".." attribute must be "The value of the Service attribute is
the common language runtime (CLR) type
name of the service implementation." -
you need to specify the .NET name of
the service implementation class here
! That's your
SessionWCF.Lib.SessionService class.
I agree with you becouse it is exacly what I've wrote :-)
You point this article: http://msdn.microsoft.com/en-us/library/aa751792.aspx
But a few lines below and you will see what it is under the hood:
new ServiceHost( typeof( MyNamespace.MyServiceImplementationTypeName) );
So when I typed:
<%# ServiceHost Language="C#" Debug="true"
Service="SessionWCF.Lib.SessionService"
CodeBehind="SessionWCF.Lib.SessionService.cs" %>
I pointed exacly: SessionWCF.Lib - namespace, SessionService - class where I have my service implemented.
I my example SessionWCF.Lib - it is both assembly name for .dll and namespace inside SessionWCF.Lib project what you can see at the top of this post when I describe second project in my solution, starting by "Second - SessionWCF.Lib, it is ..."
And again this solution WORKS perfectly without Session functionality of WCF, but it is NOT WORKING when I use WCF Session what I need...
Thanks for engagement but issue must be elsewhere...
UPDATE 2010-07-08
#marc_s was right about wrong configuration in web.config.
Proper configuration must have to be the same name as in Wcf Library:
<service behaviorConfiguration="SessionServiceBehavior" name="SessionWCF.Lib.SessionService">
Regards,
Daniel Skowroński

#marc_s was right about wrong configuration in web.config.
Proper configuration must have to be the same name as in Wcf Library:
<service behaviorConfiguration="SessionServiceBehavior" name="SessionWCF.Lib.SessionService">

Related

MachineKeyDataProtector - Invalid link when confirmation email sent through background job

I've been pulling my hair out over this. Anytime a user registration email is sent out via my windows service (background task), I get an "Invalid link".
My setup
I'm using Hangfire as a windows service on our development server. This is where the problematic GenerateEmailConfirmationToken call is happening. It's in a completely different context, outside of the ASP.NET pipeline. So I have setup machineKey values to correspond with that in the web.config of the MVC application:
In the app.config of the Windows Service Console project, which transforms to MyApp.exe.config, I have a machineKey element
In the MVC 5 project - I have a machineKey element that matches the MyApp.exe.config machineKey element.
I've verified that BOTH of these have the same machine key element data.
The Problem
When I generate a user using the ASP.NET MVC context and pipeline (IE without going through the Hangfire Background job processing), the link works fine.
When I use the background job processor, I always get invalid link. I'm all out of ideas here.
Why is this happening? Is it because the token is being generated in a different thread? How do I get around this?
Relevant code for the various projects
IoC Bootstrapping
Gets called by both applications (Windows Service and MVC Web App)
container.Register<IUserTokenProvider<AppUser, int>>(() => DataProtector.TokenProvider, defaultAppLifeStyle);
DataProtector.cs
public class DataProtector
{
public static IDataProtectionProvider DataProtectionProvider { get; set; }
public static DataProtectorTokenProvider<AppUser, int> TokenProvider { get; set; }
static DataProtector()
{
DataProtectionProvider = new MachineKeyProtectionProvider();
TokenProvider = new DataProtectorTokenProvider<AppUser, int>(DataProtectionProvider.Create("Confirmation", "ResetPassword"));
}
}
Things I've Tried
Using a DpapiDataProtectionProvider
Custom MachineKeyProtectionProvider from Generating reset password token does not work in Azure Website
The MachineKeyProtectionProvider.cs code is exactly as the linked post above.
I've also tried other purposes like "YourMom" and "AllYourTokensAreBelongToMe" to no avail. Single purposes, multiple purposes - it doesn't matter - none work.
I'm also calling HttpUtility.UrlEncode(code) on the code that gets generated in both places (Controller and Background Job).
Solution
igor got it right, except it was not a code issue. It was because of a rogue service picking up the job, which had a different machine key. I had been staring at the problem so long that I did not see a second service running.
As I understand your problem there are 2 possible places where failure could occur.
1. MachineKey
It could be that the MachineKey itself is not producing a consistent value between your 2 applications. This can happen if your machineKey in the .config file is not the same in both applications (I did read that you checked it but a simple type-o, added space, added to the wrong parent element, etc. could lead to this behavior.). This can be easily tested to rule it out as a point of failure. Also the behavior might be different depending on the referenced .net framework, MachineKey.Protect
The configuration settings that are required for the MachineKeyCompatibilityMode.Framework45 option are required for this method even if the MachineKeySection.CompatibilityMode property is not set to the Framework45 option.
I created a random key pair for testing and using this key I generated a test value I assigned to variable validValue below in the code. If you copy/paste the following section into your web.config and app.config the Unprotect of that keyvalue will work.
web.config / app.config
<system.web>
<httpRuntime targetFramework="4.6.1"/>
<machineKey decryption="AES" decryptionKey="9ADCFD68D2089D79A941F9B8D06170E4F6C96E9CE996449C931F7976EF3DD209" validation="HMACSHA256" validationKey="98D92CC1E5688DB544A1A5EF98474F3758C6819A93CC97E8684FFC7ED163C445852628E36465DB4E93BB1F8E12D69D0A99ED55639938B259D0216BD2DF4F9E73" />
</system.web>
Service Application Test
class Program
{
static void Main(string[] args)
{
// should evaluate to SomeTestString
const string validValue = "03AD03E75A76CF13FDDA57425E9D362BA0FF852C4A052FD94F641B73CEBD3AC8B2F253BB45550379E44A4938371264BFA590F9E68E59DB57A9A4EB5B8B1CCC59";
var unprotected2 = MachineWrapper.Unprotect(validValue);
}
}
Mvc Controller (or Web Api controller) Test
public class WebTestController : Controller
{
// GET: WebTest
public ActionResult Index()
{
// should evaluate to SomeTestString
const string validValue = "03AD03E75A76CF13FDDA57425E9D362BA0FF852C4A052FD94F641B73CEBD3AC8B2F253BB45550379E44A4938371264BFA590F9E68E59DB57A9A4EB5B8B1CCC59";
var unprotected2 = MachineWrapper.Unprotect(validValue);
return View(unprotected2);
}
}
Common Code
using System;
using System.Linq;
using System.Text;
using System.Web.Security;
namespace Common
{
public class MachineWrapper
{
public static string Protect()
{
var testData = "SomeTestString";
return BytesToString(MachineKey.Protect(System.Text.Encoding.UTF8.GetBytes(testData), "PasswordSafe"));
}
public static string Unprotect(string data)
{
var bytes = StringToBytes(data);
var result = MachineKey.Unprotect(bytes, "PasswordSafe");
return System.Text.Encoding.UTF8.GetString(result);
}
public static byte[] StringToBytes(string hex)
{
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
public static string BytesToString(byte[] bytes)
{
var hex = new StringBuilder(bytes.Length * 2);
foreach (byte b in bytes)
hex.AppendFormat("{0:x2}", b);
return hex.ToString().ToUpper();
}
}
}
If this passes both Console and the Web Application will get the same value and not throw a CryptographicException message Error occurred during a cryptographic operation. If you want to test with your own keys just run Protect from the common MachineWrapper class and record the value and re-execute for both apps.
2. UserManager uses Wrong Type
I would start with the previous section BUT the other failure point is that your custom machine key provider is not being used by the Microsoft.AspNet.Identity.UserManager. So here are some questions/action items that can help you figure out why this is happening:
Is container.Register the Unity IoC framework or are you using another framework?
Are you sure that your Di framework is also injecting that instance in the Microsoft.AspNet.Identity.UserManager in both the Service application as well as the Web application?
Have put a break point in public byte[] Protect of your MachineKeyDataProtector class to see if this is called in both the Service application as well as the Web application?
From examples I have seen so far (including the one you posted with the custom MachineKey solution) you need to manually bootstrap the type during application startup but then again I have not ever tried to hook into the Identity framework to replace this component using DI.
If you look at the default Visual Studio template code that is provided when you create a new MVC application the code file App_Start\IdentityConfig.cs would be the place to add this new provider.
Method:
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
Replace
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
With this
var provider = new MachineKeyProtectionProvider();
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(provider.Create("ResetPasswordPurpose"));
And this has to be configured for both applications if you are not using a common library where this is configured.

How to setup Ioc (Autofac) with Sitecore MVC

Does any one know how to setup correct IoC (Autofac) and use it with Sitecore MVC ?
I have created a specific Pipeline but it seams like resolving doesn't work when sitecore render page (Controller rendering).
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<initialize>
<processor type="MyLib.AutofacProcessor, MyLib" />
</initialize>
</pipelines>
</sitecore>
</configuration>
public class AutofacProcessor
{
public void Process(PipelineArgs args)
{
AutofacProcessor.Start();
}
public static void Start()
{
var builder = new ContainerBuilder();
builder.RegisterType<MyService>().As<IMyService>().PropertiesAutowired();
var container = builder.Build();
IDependencyResolver resolver = new AutofacDependencyResolver(container);
DependencyResolver.SetResolver(resolver);
}
}
But my property in controller is null when sitecore call it.
How to register it in Sitecore term ? In Regular ASP MVC it is quite easy.
You also need to override Sitecore's default ControllerFactory.
<processor type="Sitecore.Mvc.Pipelines.Loader.InitializeControllerFactory, Sitecore.Mvc"/>
Here's an example for NInject, it should be easily modified to do the same with AutoFAC: http://blog.istern.dk/2012/10/23/sitecore-mvc-new-ninject-controller-factory-clean-version/
I create a blog post around how to use Autofac with Sitecore MVC in order to resolve dependencies:
http://sitecorecorner.com/2016/01/20/sitecore-mvc-autofac-dependency-resolution/
You can find the code on BitBucket
The basic idea is to create an AutofacContainerFactory - to create your Container. AutofacControllerFactory - which you are going to use to resolve the dependancy and Hijack the <processor type="Sitecore.Mvc.Pipelines.Loader.InitializeControllerFactory, Sitecore.Mvc">
processor.

Castle Windsor 3.1 PerWebRequestLifestyleModule configuration

I'm using castle windsor 3.1.0.0 for dependency injection in my MVC 3.0 application.
My container is setup to provide controllers like this:
container.Register(Classes.FromThisAssembly().BasedOn<IController>().LifestylePerWebRequest());
This seems to be working as I see a new controller instance created for every request. However according to the documenation: http://docs.castleproject.org/Windsor.LifeStyles.ashx, I must also place this in my web.config:
<httpModules>
<add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor"/>
</httpModules>
which I don't have. What is the behavior of Castle Windsor if this module is missing? (The documentation says that In order to function properly per web request you must have this in your web config).
As far as I understand, the PerWebRequestLifestyle requires an IHttpModule so that it can piggy-back off the init method and the HttpApplication events such as BeginRequest.
The reason why everything seems to be working is because the module has been initialised and so the PerWebRequestLifestyle is functioning normally.
But why is that the case if you didn't include the registration module? I suspect that it is a legacy instruction and that the container will attempt a registration on its own, but this isn't documented explicitly.
If we take a peek inside CastleWindsor we find something called Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModuleRegistration. It has this method:
public static void Run()
{
Type type = Type.GetType("Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility, Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35", false);
if (type == null)
{
return;
}
MethodInfo method = type.GetMethod("RegisterModule", BindingFlags.Static | BindingFlags.Public);
if (method == null)
{
return;
}
object[] objArray = new object[] { typeof(PerWebRequestLifestyleModule) };
method.Invoke(null, objArray);
}
What is DynamicModuleUtility? A quick search reveals a page written by K. Scott Allen called DynamicModuleUtility.
The DynamicModuleUtility will let you install an HTTP module into the ASP.NET pipeline without making any changes to web.config file.
This is only my speculation as to what's going on. You'd have to ask the creators of Castle Windsor for details on exactly how things are working.

Does AOP with AspectJ works with method from Managed Bean called from the view in JSF2?

I’m currently facing a Problem using a combination of JSF 2 and AOP with AspectJ annotation.
I don't know if Spring AOP is playing a role here...(I didn't well understand difference between SPRING AOP, ASPECTJ, GOOGLE GUICE...that's an another question)
I'm trying to send an e-mail after i added some values in my database via click on a form in jsf view.
I have a managedBean AddPartipant handled by JSF (linked to a view) to add participant via a form. I want to intercept the method who makes the change in database and send an email just after this action.
I have a spring bean SendMailBoImpl with a method to send an email.(sending works ok)
I found using a AOP was a good way. It's works only when i trying to make it works in a main...not in the complete webapp. I read some stuffs about problem context spring / Jsf but don't found a solution...yet...
I know my method to add data in the database via the view is ok...but the mail is never sent whereas the database is modified.
Somebody has an idea ?
Thanks a lot :)
AddParticipant ManagedBean :
public class AddParticipant implements Serializable{
//DI via Spring
ParticipantBo participantBo;
private String id_study ;
private Participant aParticipant = new Participant();
//getters and setters
public void addParticipant(){
aParticipant.setId_study (id_study);
...
participantBo.save(aParticipant);
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Ajout du participant "+id_study+" dans l'étude "+ study_name));
}
MaiBo Service :
#After("execution(* com.clb.genomic.lyon.beans.AddParticipant.addParticipant(..))")
public void sendMail() {
....
mailSender.send(message);
....
}
My bean config :
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean id="addParticipant" class="com.clb.genomic.lyon.beans.AddParticipant"/>
<bean id="sendMailBo" class="com.clb.genomic.lyon.bo.SendMailBoImpl">
<property name="mailSender" ref="mailSender" />
<property name="simpleMailMessage" ref="customeMailMessage" />
</bean>
When i do this it's working :
ApplicationContext appContext = new ClassPathXmlApplicationContext
( "classpath:webConfiguration/applicationContext.xml");
AddParticipant aspect = (AddParticipant) appContext.getBean("addParticipant");
aspect.addParticipant();
Solved base on the read of this : http://kumarnvm.blogspot.fr/2012/07/using-spring-to-manage-jsf-september-10_14.html

MSMQ Trigger to Call a Windows Service

When ever there is a message in the queue, I need my windows service to process the message in the queue.
I was thinking that it would probably be best to set up a windows service and when ever there is a message in the queue, that MSMQ should trigger, firing a call to the windows service.
Does anyone know how to do this?
If you wanted to, you can host a WCF ServiceHost in the Windows Service, which will automatically pick up the messages as they are received. No hook-ups to MSMQ are required. WCF will automatically pull the messages into the service when they appear.
Lets say you are already writing to the MSMQ private queue 'test'. To write a running Windows Service, you do something like this, forgive the example for method accuracy in the service:
namespace WcfService
{
public class Order
{
public int ID { get; set; }
}
[ServiceContract]
public interface IOrderService
{
[OperationContract(TransactionScopeRequired=true)]
void ProcessOrder(Order order);
}
public class OrderService : IOrderService
{
public void ProcessOrder(Order order)
{
Debug.Print("Order ID: ", order.ID);
}
}
}
namespace Client
{
public class WindowsService : IDisposable
{
private ServiceHost host = null;
// TODO: Implement static void Main to initialize service
// OnStart
public void OnStart()
{
if(host == null)
host = new ServiceHost( typeof ( OrderService ) );
host.Open();
}
public void OnStop()
{
host.Close();
}
public void Dispose()
{
// TODO: Implement Dispose() pattern properly
if(host!=null)
host.Dispose();
}
}
}
Then configuration for the Windows Service to read from MSMQ
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<bindings>
<netMsmqBinding>
<binding name="readFromQueueBinding" exactlyOnce="false">
<security mode="None"/>
</binding>
</netMsmqBinding>
</bindings>
<services>
<service name="WcfService.OrderService">
<endpoint address="net.msmq://localhost/private/test"
binding="netMsmqBinding"
contract="WcfService.IOrderService"
name="IOrderService_Msmq_Service"
bindingConfiguration="readFromQueueBinding"/>
</service>
</services>
</system.serviceModel>
</configuration>
This is an overly broad question, but you can create a Windows service that listens to a queue syncronously or asynchronously, receives messages and processes them as they arrive. As to how to accomplish that, the default service project provided by Visual Studio is a good start. From there you can create a class that gets instantiated when the service starts, binds to the queue and calls Receive or BeginReceive (sync or async) to get messages and process them.
Another option is to use activation services. This is potentially more complicated from an environmental perspective, and you need a certain version of Windows and .NET for it to be available.
Finally there's MSMQ Triggers. This is a service that is (optionally) installed along with MSMQ itself. It can be configured to monitor a queue and perform an action when a message arrives. This would be the simplest option, however if you opt for this then I'd suggest just creating a normal EXE instead of a service, and using the trigger to execute it.
This article covers some of the pros and cons of each approach; I'd suggest reading it before you make a decision.

Resources