When will my new HttpModule's Init() method fire? - sharepoint-2010

Using event handlers in my Site-scoped feature's Feature Receiver, I'm adding my HttpHandler to my configuration (I'm new to this, so the code is a bit disjointed, as I've found it here and there).
public override void FeatureActivated(SPFeatureReceiverProperties properties) {
var site = (SPSite)properties.Feature.Parent;
var webApp = site.WebApplication;
if (!webApp.IsAdministrationWebApplication) {
var modification = new SPWebConfigModification("add[#name='SharePointNinjectHttpModule']", "configuration/system.web/httpModules");
modification.Owner = "addSharePointNinjectHttpModule";
modification.Sequence = 0;
modification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
modification.Value = #"<add name=""SharePointNinjectHttpModule"" type=""Foo.Bar.SharePointNinjectHttpModule,Foo.Bar, Version=1.0.0.0, Culture=neutral, PublicKeyToken=****************"" />";
webApp.WebConfigModifications.Add(modification);
try {
webApp.WebService.ApplyWebConfigModifications();
webApp.Update();
}
catch (SecurityException e) {
// todo ApplyWebConfigModifications throws "Access Denied" SecurityException when activating via Site Settings
}
}
}
public override void FeatureDeactivating(SPFeatureReceiverProperties properties) {
var site = (SPSite)properties.Feature.Parent;
var webApp = site.WebApplication;
if (!webApp.IsAdministrationWebApplication) {
var oCollection = webApp.WebConfigModifications;
var iStartCount = oCollection.Count;
for (int c = iStartCount - 1; c >= 0; c--) {
SPWebConfigModification oModification = oCollection[c];
if (oModification.Owner == "addSharePointNinjectHttpModule") {
oCollection.Remove(oModification);
}
}
if (iStartCount > oCollection.Count) {
try {
webApp.WebService.ApplyWebConfigModifications();
webApp.Update();
}
catch (SecurityException e) {
// todo ApplyWebConfigModifications throws "Access Denied" SecurityException when deactivating via Site Settings
}
}
}
}
My SharePoint instance's web.config httpModules section when the feature is not active:
<httpModules>
</httpModules>
And when it is:
<httpModules>
<add name="SharePointNinjectHttpModule" type="Foo.Bar.SharePointNinjectHttpModule,Foo.Bar, Version=1.0.0.0, Culture=neutral, PublicKeyToken=****************" />
</httpModules>
So it seems like the feature receiver event handlers are doing their job (maybe I'm missing something?).
And here's the HttpModule:
using System;
using System.Web;
using Foo.Bar.Models;
using Ninject;
namespace Foo.Bar {
public class SharePointNinjectHttpModule : IHttpModule {
public void Init(HttpApplication context) {
if (Kernel == null) {
Kernel = new StandardKernel();
Kernel.Bind<IRepository>().To<Repository>();
}
}
public static IKernel Kernel { get; private set; }
public void Dispose() {}
private static IKernel GetKernel() {
IKernel result = new StandardKernel();
result.Bind<IRepository>().To<Repository>();
return result;
}
}
}
The Init() method of my HttpModule never fires. When should I expect it to fire, and why isn't that happening?

The following change to FeatureActivated() resolved the problem I was having:
var modification = new SPWebConfigModification("add[#name='SharePointNinjectHttpModule']", "configuration/system.webServer/modules");
I was injecting the module in the wrong section of my web.config.
Original: configuration/system.web/httpModules
Changed: configuration/system.webServer/modules
Once I made the above change, I was correctly adding the httpModule
Once I was correctly adding the httpModule, my Init() fired immediately.

Related

Detect disconnect in WCF

We're building a WCF server (.NET 4.5). It will only use net.pipe transport.
When a client closes the PIPE connection, the server gets unhandled CommunicationException, and terminates.
Q1. How do I handle the CommunicationException so the server does not terminate and continues serving other clients?
Q2. In the handler, how do I get SessionId of the session that was aborted? I need this to do clean up some session-specific data.
Thanks in advance!
contract
[ServiceContract(CallbackContract = typeof(IContractCallback))]
public interface IContractServer
{
[OperationContract(IsOneWay = true)]
void Connect(bool status);
[OperationContract(IsOneWay = false)]
void Disconnect(IContractServer _channelCallback);
[OperationContract(IsOneWay = true)]
void Play(bool status);
}
service
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class Service : IContractServer
{
public List<IContractCallback> _channeList = new List<IContractCallback>();
public void Connect(bool status)
{
IContractCallback a = OperationContext.Current.GetCallbackChannel<IContractCallback>();
int call = 0;
foreach (var callBack in _channeList)
{
if (callBack == a)
{
call++;
}
}
if (call == 0)
{
_channeList.Add(a);
a.ConnectCallback(true);
}
else
{
a.ConnectCallback(false);
}
}
public void Disconnect(IContractServer _channelCallback)
{
foreach (var contractCallback in _channeList)
{
if (contractCallback == _channelCallback)
{
_channeList.Remove(contractCallback);
}
}
}
public void Play(bool status)
{
foreach (var contractCallback in _channeList)
{
contractCallback.PlayCallback(status);
}
}
}
client
using System.ComponentModel;
using System.ServiceModel;
using System.Windows;
using Host;
namespace VideoPlayer
{
public partial class MainWindow : Window, IContractCallback
{
private IContractServer Proxy = null;
public MainWindow()
{
InitializeComponent();
InstanceContext context = new InstanceContext(this);
DuplexChannelFactory<IContractServer> factory = new DuplexChannelFactory<IContractServer>(context, new NetNamedPipeBinding(), "net.pipe://localhost");
Proxy = factory.CreateChannel();
Proxy.Connect(true);
}
public void ConnectCallback(bool status)
{
MessageBox.Show(status ? "connected" : "no connected");
}
public void PlayCallback(bool status)
{
if (status)
{
MessageBox.Show("status true");
}
else
{
MessageBox.Show("status false");
}
}
private void ButtonPlay(object sender, RoutedEventArgs e)
{
Proxy.Play(true);
}
private void MainWindow_OnClosing(object sender, CancelEventArgs e)
{
//хочу отправить сообщение о закрытии
Proxy.Disconnect(Proxy);
}
I faced with this problem before in my duplex services when an event raised from server side the exception occurred if there was no alive channel between client and server so server dropped to Fault state and all next requests won't be responded,
For this reason I came to this conclusion to check the channel and if it was alive then let call back methods to be raised.
In service side the trick would be like ↓
bool IsChannelAlive()
{
Logging logging = new Logging(LogFile);
try
{
if (((ICommunicationObject)_callbackChannel).State == CommunicationState.Opened)
{
logging.Log(LoggingMode.Prompt, "Channeld is still alive, can raise events...");
return true;
}
}
catch (Exception exp)
{
logging.Log(LoggingMode.Error, "IsChannelAlive()=> failed, EXP: {0}", exp);
}
logging.Log(LoggingMode.Warning, "Channeld is not alive so events won't raised...");
return false;
}
and in one of my events I use it like :
void stran_OperationTimedOut(object sender, EventArgs e)
{
if (IsChannelAlive())
_callbackChannel.OnOperationTimedOut();
}
But for a while I use this trick to know closed channel to do something:
public ImportService()
{
//Handle ContextClose to Audit all actions made in session
OperationContext.Current.InstanceContext.Closed += delegate
{
//Here
};
}
which is not reliable.
I am still using that IsAliveChannel() in my services.
Hope this answer resolve your problem or give you the clue.

wcf not picking up the code

I have created a wcf service, but when i am installing it on server, it is not picking the code.
Here is my program.cs class:
log4net.Config.XmlConfigurator.Configure();
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
and here is my service1.cs:
public Service1()
{
logger.Info("log started");
InitializeComponent();
}
protected override void OnStart(string[] args)
{
logger.Info("Service Started");
timerHandlingFirst.Elapsed += new ElapsedEventHandler(OnElapsedTimeFirst);
timerHandlingFirst.Enabled = true;
timerHandling.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timerHandling.Enabled = true;
}
I have attached used log4net dll, but its not even generating the logs.

Nancy - Unable to resolve type: NHibernate.ISession

My CustomBootstrapper looks like below
public class CustomBootstrapper : DefaultNancyBootstrapper
{
protected override NancyInternalConfiguration InternalConfiguration
{
get
{
//This will tell Nancy it won't have to look in the Nhibernate assemblies for implementations of our interfaces.
return NancyInternalConfiguration
.Default
.WithIgnoredAssembly(asm => asm.FullName.StartsWith("NHibernate", StringComparison.InvariantCulture))
.WithIgnoredAssembly(asm => asm.FullName.StartsWith("Fluent", StringComparison.InvariantCulture))
.WithIgnoredAssembly(asm => asm.FullName.StartsWith("Iesi", StringComparison.InvariantCulture));
}
}
protected override void ConfigureRequestContainer(TinyIoCContainer container, NancyContext context)
{
base.ConfigureRequestContainer(container, context);
//container.Register((c, p) => SessionFactory.OpenSession());
container.Register(SessionFactory.OpenSession());
}
}
I have a repository which accepts ISession as a constructor dependency. When I run my application I get an error saying Unable to resolve type: NHibernate.ISession
I can confirm that
My bootstrapper is picked up by Nanacy
The ISession registration code is executed
I have tried commenting out .WithIgnoredAssembly(asm => asm.FullName.StartsWith("NHibernate", StringComparison.InvariantCulture)) from property InternalConfiguration
I get the error with both of the ways of registering component (one is commented in my code)
I have looked at similar other questions on SO and none has helped so far.
I've done a sample project that uses NH with Nancy. In the bootstrapper I set up:
a BeforeRequest hook that creates the session and binds it to the session context
a AfterRequest hook that commits the session
an OnError hook that rolls back
The code is as follows:
public class Bootstrapper : WindsorNancyBootstrapper
{
// other stuff
protected override void ApplicationStartup(IWindsorContainer container, IPipelines pipelines)
{
base.ApplicationStartup(container, pipelines);
// other setup
ConfigureNHibernateSessionPerRequest(container, pipelines);
}
private void ConfigureNHibernateSessionPerRequest(IWindsorContainer container, IPipelines pipelines)
{
pipelines.BeforeRequest += ctx => CreateSession(container);
pipelines.AfterRequest += ctx => CommitSession(container);
pipelines.OnError += (ctx, ex) => RollbackSession(container);
}
private Response RollbackSession(IWindsorContainer container)
{
var sessionFactory = container.Resolve<ISessionFactory>();
if (CurrentSessionContext.HasBind(sessionFactory))
{
var requestSession = sessionFactory.GetCurrentSession();
requestSession.Transaction.Rollback();
CurrentSessionContext.Unbind(sessionFactory);
requestSession.Dispose();
}
return null;
}
private Response CreateSession(IWindsorContainer container)
{
var sessionFactory = container.Resolve<ISessionFactory>();
var requestSession = sessionFactory.OpenSession();
CurrentSessionContext.Bind(requestSession);
requestSession.BeginTransaction();
return null;
}
private AfterPipeline CommitSession(IWindsorContainer container)
{
var sessionFactory = container.Resolve<ISessionFactory>();
if (CurrentSessionContext.HasBind(sessionFactory))
{
var requestSession = sessionFactory.GetCurrentSession();
requestSession.Transaction.Commit();
CurrentSessionContext.Unbind(sessionFactory);
requestSession.Dispose();
}
return null;
}
}

Signalr + unity DI

I have used Signalr in my MVC4 project succesfully by the conventional method by setting up a normal hub, including the JS file /signalr/hubs and it works.
Now I am trying to setup DI with unity:
In Global.asax
UnityContainer = Bootstrapper.Initialise();
var unityDependencyResolver = new UnityDependencyResolver(UnityContainer);
// Used for MVC
DependencyResolver.SetResolver(unityDependencyResolver);
// Used for SignalR
GlobalHost.DependencyResolver = new SignalRUnityDependencyResolver(UnityContainer);
RouteTable.Routes.MapHubs();
Bootstrapper.cs
public static IUnityContainer Initialise()
{
var unityContainer = new UnityContainer();
unityContainer.RegisterType<IUsers, Users>();
unityContainer.RegisterType<ChatHub>(new InjectionFactory(CreateMyHub));
return unityContainer;
}
private static object CreateMyHub(IUnityContainer p)
{
return new ChatHub(p.Resolve<IUsers>());
}
And the hub:
public class UserHub : Hub
{
private readonly IUsers _users;
public ChatHub(IUsers users)
{
_users = users;
}
public void Send(String message)
{
Clients.All.addMessage(message);
}
}
My SignalRUnityDependencyResolver.cs
public class SignalRUnityDependencyResolver : DefaultDependencyResolver
{
private readonly IUnityContainer _container;
public SignalRUnityDependencyResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container", "Containet cannot be null");
}
_container = container;
}
public override Object GetService(Type serviceType)
{
return _container.IsRegistered(serviceType) ? _container.Resolve(serviceType) : base.GetService(serviceType);
}
public override IEnumerable<Object> GetServices(Type serviceType)
{
return _container.IsRegistered(serviceType) ? _container.ResolveAll(serviceType) : base.GetServices(serviceType);
}
}
This is working for non hubs because all dependencies resolve, but now the javascript file <script src="~/signalr/hubs"></script> is not generated anymore.
How can I debug this generation of JS and where could be the culprit?
you can use this in config
EnableJavaScriptProxies = false
the code like this:
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
EnableJSONP = true,
EnableJavaScriptProxies = false
};
map.RunSignalR(hubConfiguration);
});

How to handle NHibernate sessions in an MVC4 project

I currently get my session from the globalasax as follows...
public class MvcApplication : HttpApplication
{
public static readonly ISessionFactory SessionFactory = NHibernateHelper.CreateSessionFactory();
public MvcApplication()
{
BeginRequest += delegate
{
if (!HttpContext.Current.Request.Url.AbsolutePath.StartsWith("/_cassette/"))
{
CurrentSession = SessionFactory.OpenSession();
CurrentSession.FlushMode = FlushMode.Auto;
}
};
EndRequest += delegate
{
if (CurrentSession != null)
{
CurrentSession.Flush();
CurrentSession.Dispose();
}
};
}
public static ISession CurrentSession
{
get { return (ISession) HttpContext.Current.Items["current.session"]; }
set { HttpContext.Current.Items["current.session"] = value; }
I was looking at the Sharp Architecture Transaction attribute and a similar one http://weblogs.asp.net/srkirkland/archive/2009/09/03/asp-net-mvc-transaction-attribute-using-nhibernate.aspx but whats the best way of handling sessions in an MVC4 project to make use of none-implicit transactions ala http://nhprof.com/Learn/Alerts/DoNotUseImplicitTransactions
I can easily wrap everything by adding the transaction/commit to the begin request/end request but the attribute method seems cleaner (actually handles errors); or should I be using a filter now?
What is the best practice for MVC4 with NHibernate?
Your current session handling has one serious problem (been there done that ;)). CurrentSession is static and hence it is shared among all concurrent requests. NHibernate's ISession is NOT thread safe (unlike ISessionFactory which IS thread safe).
NHibernate offers session contextes into which the session can be bound and after which the bound session can be acquired from session factory (.GetCurrentSession() -method). To be able to use CurrentSessionContext like in the next example you need to tell NHibernate which session context to use. For web applications WebSessionContext is good choice.
When I'm using MVC I write an action filter which takes care of the session handling. Here is an example (written for MVC 2):
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class TransactionAttribute : ActionFilterAttribute
{
public TransactionAttribute()
{
Order = 100;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
CurrentSessionContext.Bind(NHibernateManager.SessionFactory.OpenSession());
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
var session = CurrentSessionContext.Unbind(NHibernateManager.SessionFactory);
session.Close();
session.Dispose();
}
}
It shouldn't be too much of a problem to add transaction management also into the same filter. In OnActionExecuting-method you could open transaction with ISession's .BeginTransaction() and in OnActionExecuted you get the current transaction from ISession's Transaction-property which can then be committed and disposed.
There's another way to implement the "Session per request pattern" - httpModule.
public class NHibernateModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += context_BeginRequest;
context.EndRequest += context_EndRequest;
}
private static void context_BeginRequest(object sender, EventArgs e)
{
//use my session manager
ISession session = SessionManager.Instance.OpenSession();
CurrentSessionContext.Bind(session);
}
private static void context_EndRequest(object sender, EventArgs e)
{
ISessionFactory sessionFactory = SessionManager.Instance.SessionFactory;
ISession session = CurrentSessionContext.Unbind(sessionFactory);
if (session == null) return;
if (session.Transaction != null)
{
if (session.Transaction.IsActive)
{
//if there is an active session, commit it
session.Transaction.Commit();
}
else
{
//
session.Transaction.Rollback();
}
}
session.Close();
}
<configuration>
<!-- IIS 6 -->
<system.web>
<httpModules>
<add name="NHibernateModule" type="NHibernateModule"/>
</httpModules>
</system.web>
<!-- IIS 7 and Cassini. -->
<system.webServer>
<modules>
<add name="NHibernateModule" type="NHibernateModule"/>
</modules>
</system.webServer>
</configuration>
ActionFilterAttribute way has the question: how it will behave with a few actions in one HTTP request?
This pattern suggests that one NHibernate session be opened per HTTP request.
Following up to Ultor's answer, plus Ayende's "Refactoring toward frictionless & odorless code: What about transactions?" article, and, finally, because I have already set the dependency resolver of the application in Application_Start using the following:
DependencyResolver.SetResolver(new MyDependencyResolver())
I changed the TransactionAttribute class to be as follows:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class SessionAttribute : ActionFilterAttribute {
static readonly ISessionFactory SessionFactory = BuildSessionFactory();
static ISessionFactory BuildSessionFactory() {
return (ISessionFactory) DependencyResolver.Current.GetService(typeof (ISessionFactory));
}
public override void OnActionExecuting(ActionExecutingContext filterContext) {
var sessionController = filterContext.Controller as SessionController;
if (sessionController == null)
return;
if (sessionController.NHibernateSession == null) {
sessionController.NHibernateSession = SessionFactory.OpenSession();
}
sessionController.NHibernateSession.BeginTransaction();
CurrentSessionContext.Bind(sessionController.NHibernateSession);
}
public override void OnActionExecuted(ActionExecutedContext filterContext) {
var sessionController = filterContext.Controller as SessionController;
if (sessionController == null) return;
var session = CurrentSessionContext.Unbind(SessionFactory);
if (session == null) return;
if (session.Transaction != null) {
if (!session.Transaction.IsActive) return;
if (filterContext.Exception != null)
session.Transaction.Rollback();
else
session.Transaction.Commit();
}
session.Close();
session.Dispose();
}
}
And the base controller defined as such:
public class SessionController : Controller {
public ISession NHibernateSession { get; set; }
}
Now, persistence in my controller becomes as easy as:
[HttpGet, Session]
public ActionResult CreateOrUpdate(Guid id = new Guid()) {
var company = GetCompany(id);
if (company == null) throw new HttpException(404, "Not Found");
return View(company);
}
[HttpPost, ValidateAntiForgeryToken, Session]
public ActionResult CreateOrUpdate(Company passedInCompany) {
var company = NHibernateSession.Get<Company>(passedInCompany.Id);
if (company == null) throw new HttpException(404, "Not Found");
UpdateModel(company);
if (ModelState.IsValid) {
NHibernateSession.SaveOrUpdate(company);
return RedirectToAction("Index");
}
return View(company);
}
Company GetCompany(Guid id) {
Company company;
if (id == Guid.Empty) {
company = companyBuilder.Create();
} else {
company = NHibernateSession.Get<Company>(id);
NHibernateSession.Flush();
}
return company;
}
There are some good answers here but my recommendation is to use a dependency inject framework (I like Ninject) to implement session-per-request. This allows you to use constructor injection on the controllers to inject the ISession.