I's like to process the IP address and user agent of each signalr connection to my hub. To do this, I have overridden the OnConnected method as shown below.
public override Task OnConnected()
{
string UserAgent = Context.Headers["User-Agent"];
var Request = Context.Request.GetHttpContext().Request;
string IPAddress = Request.UserHostAddress;
// code to process IP address and user agent goes here
return base.OnConnected();
}
Is there a more robust way to retrieve the IP address? The call to Context.Request.GetHttpContext().Request sometimes fails. Using fiddler, I can see that most failures occur if web sockets are used for the underlying connection.
I would suggest pulling the IP address from OWIN's environment dictionary directly:
http://owin.org/
http://owin.org/spec/owin-1.0.0.html
http://owin.org/spec/CommonKeys.html
Request.GetHttpContext() actually works by getting the HttpContextBase from the environment dictionary:
/// <summary>
/// Returns the <see cref="HttpContextBase"/> for this <see cref="IRequest"/>.
/// </summary>
/// <param name="request">The request</param>
public static HttpContextBase GetHttpContext(this IRequest request)
{
object httpContextBaseValue;
if (request.Environment.TryGetValue(typeof(HttpContextBase).FullName, out httpContextBaseValue))
{
return httpContextBaseValue as HttpContextBase;
}
return null;
}
You could write something similar specifically for getting the IP address:
public static string GetRemoteIpAddress(this IRequest request)
{
object ipAddress;
if (request.Environment.TryGetValue("server.RemoteIpAddress", out ipAddress))
{
return ipAddress as string;
}
return null;
}
Not only is this likely more robust, but it also has a much better chance of still working if you port your application to another web server (or perhaps self-host).
Related
I was trying to test message sent from tested actor, but getting timeout exception and a Dead letter info.
As I am using ninject - created a mock method which always replays with probe actor reference.
Am I missing something here?
Assert.Fail failed. Failed: Timeout 00:00:03 while waiting for a message of type System.Type
at Akka.TestKit.TestKitBase.InternalExpectMsgEnvelope(Nullable`1 timeout, Action`2 assert, String hint, Boolean shouldLog)
at Akka.TestKit.TestKitBase.InternalExpectMsgEnvelope(Nullable`1 timeout, Action`1 msgAssert, Action`1 senderAssert, String hint)
at Akka.TestKit.TestKitBase.InternalExpectMsg(Nullable`1 timeout, Action`1 msgAssert, String hint)
at Akka.TestKit.TestKitBase.ExpectMsg(T message, Nullable`1 timeout, String hint)
at
AutoApply.UnitTests.SomethingProcessorActors.SomethingProcessorActorTests.SomethingProcessorActorWhenMergeDataAndGetsNoProfilesLogsThat()
in SomethingProcessorActorTests.cs: line 58
[WARNING][12/02/2016 16:12:43][Thread 0009][akka://test/user/testProbe] DeadLetter from [akka://test/temp/d]
to [akka://test/user/testProbe]:
[INFO][12/02/2016 16:12:43][Thread 0011][akka://test/user/testProbe] Message
GetOneSomethingAndRemoveFromList from akka://test/temp/d to
akka://test/user/testProbe was not delivered. 1 dead letters
encountered.
Debug Trace:
Setting probe reference: akka://test/user/testProbe
GetDataActorPath for:SomethingsDataActor
GetDataActorPath =>akka://test/user/testProbe
GetDataActorPath for:SomethingCollectorActor
GetDataActorPath =>akka://test/user/testProbe
[TestClass]
public class SomethingProcessorActorTests : TestKit
{
/// <summary>The factory helper</summary>
private IMockingExtension factoryHelper;
private TestProbe probeActorRef;
/// <summary>Configurations this instance.</summary>
[TestInitialize]
public void Config()
{
this.probeActorRef = this.CreateTestProbe("testProbe");
this.factoryHelper = new MockingFactoryHelper();
this.factoryHelper.SetProbe(this.probeActorRef.TestActor);
}
/// <summary>Somethings the processor actor when merge data and gets no profiles logs that.</summary>
[TestMethod]
public void SomethingProcessorActorWhenMergeDataAndGetsNoProfilesLogsThat()
{
// arrange
var actor =
this.Sys.ActorOf(
Props.Create(() => new SomethingProcessorActor(this.factoryHelper as IActorPathAndFactory)),
"SomethingActor");
// act
actor.Tell(new SomethingProcessorActor.ProcessSomethings());
// assert
this.probeActorRef.ExpectMsgFrom<SomethingsDataActor.GetOneSomethingAndRemoveFromList>(actor, new TimeSpan(0, 0, 0, 5));
}
}
=======================
public partial class SomethingProcessorActor : ReceiveActor
{
/// <summary>The helper</summary>
private readonly IActorPathAndFactory helper;
/// <summary>The log</summary>
private readonly ILoggingAdapter log = Context.GetLogger();
/// <summary>The vote execution profile</summary>
private List<SomethingProcessingObject> voteExecutionProfile = new List<SomethingProcessingObject>();
/// <summary>
/// Initializes a new instance of the <see cref="SomethingProcessorActor"/> class.
/// </summary>
/// <param name="helper">
/// The helper.
/// </param>
public SomethingProcessorActor(IActorPathAndFactory helper)
{
this.helper = helper;
this.Receive<ProcessSomethings>(
x =>
{
this.log.Debug("Received: ProcessSomethings");
this.BecomeStacked(this.Working);
this.RetriveSomethingAndPushForProcessing();
});
}
/// <summary>Supervisors strategy.</summary>
/// <returns>Supervisors strategy for that actor</returns>
protected override SupervisorStrategy SupervisorStrategy()
{
return new AllForOneStrategy(10, 3000, Decider.From(x => Directive.Stop));
}
/// <summary>
/// The merge data.
/// </summary>
private void RetriveSomethingAndPushForProcessing()
{
this.log.Debug($"Processing Somethings...");
var SomethingActor1 = this.helper.GetActorPath(ActorsEnum.SomethingsDataActor);
var SomethingActor2 = this.helper.GetActorPath(ActorsEnum.SomethingCollectorActor);
var something = (SomethingDto)SomethingActor1.Ask(new SomethingsDataActor.GetOneSomethingAndRemoveFromList()).Result;
while (Something.SomethingId>0)
{
this.log.Debug($"Sending data to SomethingCollector with Something id: {Something.SomethingId}");
SomethingActor2.Tell(new SomethingCollectorActor.ProcessSomethingDto(Something));
Something = (SomethingDto)SomethingActor1.Ask(new SomethingsDataActor.GetOneSomethingAndRemoveFromList()).Result;
}
this.log.Debug("Sending data to SomethingCollector -- ALL SENT");
this.UnbecomeStacked();
}
The mock objects just send probe actor as per every request
public ActorSelection GetActorPath(ActorsEnum actorsEnum)
{
Debug.WriteLine("GetDataActorPath for:" + actorsEnum);
Debug.WriteLine("GetDataActorPath =>" + this.probeRef.Path);
return this.Sys.ActorSelection(this.probeRef.Path);
}
public void SetProbe(IActorRef actorRef)
{
Debug.WriteLine("Setting probe reference: " + actorRef.Path);
this.probeRef = actorRef;
}
ignition overview
Ok so a few things.
First of all: You are expecting on a message of the type: SomethingsDataActor.GetOneSomethingAndRemoveFromList.
But it doesn't look like you are actually passing this message to an actorref that is represented by the testprobe. But its hard to be sure since you only pasted halve the code.
Second:
Using ask inside an actor is considered an anti pattern, and can easily be avoided by employing a more conversationalist style of communication.
Using actor.ask().Result is even worse because it can lead to deadlocks if your not carefull. (what happens when the database actor crashes because your network is down? potentially no response will ever be send back and the default Ask timeout is infinite)
Ask should only really be used to communicate with an actor from outside the actor system.
The problem was with mocking class that was inhering TestClass,
decided for that to have "Actor System Reference"
return this.Sys.ActorSelection(this.probeRef.Ref.Path);
but should be:
return this.probeRef.ActorSelection(this.probeRef.Ref.Path);
This inheritance was creating a second independednt actor system.....
Thanks #Dantar for help!
Update: I was at Build 2013, and Mark Simms looked at this and confirmed that HTTP request leaving the router does have a "Body" in the request. He felt that this was caused by the Get arriving at the SB, then packaged to be routed, then the package is managed again as a Messsage type, before sending it back out again. In between the packaging and routing, properties are left in the body of the request - which violates protocol for the "GET". All this however lives within MS framework either in the .NET, or in the ServiceBus. As the body is immutable (at least I can't find a way to alter it), the only means is to duplicate the request, and then update the original request on the way out.
This is a small part of a routing application that takes in a HTTP GET/POST request from a Azure ServiceBus endpoint, brings it down via the relay channel to my local workstation, where I rewrite the URL, and send it to my local web service.
Here is the interface - generic so that it can receive any type of call to a controller/action URL
// The Router, and general concept of how to recieve from the SB and redirect was taken from
// Tony Sneed Blog - which he documented here: http://blog.tonysneed.com/2012/04/24/roll-your-own-rest-ful-wcf-router/
//
[ServiceContract(Namespace = "urn:Twiddler")]
public interface IRoutingService
{
[WebInvoke(UriTemplate = "")]
[OperationContract(AsyncPattern = true, Action = "*", ReplyAction = "*")]
IAsyncResult BeginProcessRequest(Message requestMessage, AsyncCallback asyncCallback, object asyncState);
Message EndProcessRequest(IAsyncResult asyncResult);
}
}
Here is the code:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,
AddressFilterMode = AddressFilterMode.Any, ValidateMustUnderstand = false)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class RoutingService : IRoutingService, IDisposable
{
private IRoutingService _client;
/// <summary>
/// when a message is received from the SB, it arrives here as simply a message -
/// </summary>
/// <param name="requestMessage"></param>
/// <param name="asyncCallback"></param>
/// <param name="asyncState"></param>
/// <returns></returns>
public IAsyncResult BeginProcessRequest(Message requestMessage, AsyncCallback asyncCallback, object asyncState)
{
string RequestMessageAction = requestMessage.Headers.Action;
IAsyncResult asyncResult = null;
//if the full URI for the namespace does not match the one contructed in Twiddler, then pass it through - we have nothing to do with it!
if (requestMessage.Headers.To.AbsoluteUri.Contains(Utilities.ServiceFormBridge.NameSpaceName) && requestMessage.Headers.To.AbsoluteUri.Contains(Utilities.ServiceFormBridge.EndPointName) == false)
return asyncResult;
//as the service bus will accept anything in terms of controllers and actions, we only need alter the DestinationAddress.Authority (host and port)
var RewriteTheURL = requestMessage.Headers.To.AbsoluteUri.Replace(string.Format("http://{0}.servicebus.windows.net/{1}/", ServiceFormBridge.NameSpaceName, ServiceFormBridge.EndPointName), ServiceFormBridge.DestinationWebSite);
Uri DestinationAddress = new Uri(RewriteTheURL);
System.ServiceModel.ChannelFactory<IRoutingService> factory = null;
factory = new ChannelFactory<IRoutingService>(new WebHttpBinding(), DestinationAddress.AbsoluteUri);
WebHeaderCollection httpHeaders = WebOperationContext.Current.IncomingRequest.Headers;
httpHeaders.Remove("Host");
httpHeaders.Add("Host", DestinationAddress.Authority); //give it the new host that we are re-directing to
httpHeaders.Remove("Connection"); //todo: not sure I need this, but without it there is an exception between Keep-Alive and Closed
// Set factory and message address
factory.Endpoint.Address = new EndpointAddress(DestinationAddress);
requestMessage.Headers.To = DestinationAddress;
_client = factory.CreateChannel();
asyncResult = _client.BeginProcessRequest(requestMessage, asyncCallback, asyncState);
return asyncResult;
}
}
On the BeginProcessRequest, I get an exception:
Protocol Violation: Cannot send a content-body with this verb-type
Which I have researched and I understand that under a GET request, there can't be anything in the body of the request.
As my code works for a POST, I can only assume that for some reason, there is something in the body.
However, as the originating request was a GET from a browser using the URL of the ServiceBus, I'm not sure why there would be anything in the body.
So:
I'm thinking I'm doing something in the code that is causing me a problem - if so I would like to know what!
If there is something in the incoming request, how can I remove it so I don't get the violation?
Any other suggestions, improvements to the code?
Placing this attribute on the operation, [WebInvoke(UriTemplate = "")], supports POST by default, but you can pass a parameter specifying other verbs, such as PUT, DELETE, etc. However, GET is supported by a different attribute, [WebGet]. I would suggest adding additional operations to the router, one with WebGet, and others with WebInvoke and different HTTP verbs.
For testing the many headaches of IIS/WCF implementation from scratch, I built the HelloWorld service and client walked through (very nicely) here. I added endpoints for net.tcp, and the service is working properly end-to-end for both bindings under IIS 7.5 (on Windows 7) in its own ApplicationPool called HW.
What I'm trying to get working is the announced AutoStart and Preload (or "pre-warm caching") features. I've followed the instructions laid out here and here (quite similar to one another, but always good to have a second opinion) very closely. Which means I
1) Set the application pool startMode...
<applicationPools>
<!-- ... -->
<add name="HW" managedRuntimeVersion="v4.0" startMode="AlwaysRunning" />
</applicationPools>
2) ...enabled serviceAutoStart and set a pointer to my serviceAutoStartProvider
<site name="HW" id="2">
<application path="/" applicationPool="HW" serviceAutoStartEnabled="true" serviceAutoStartProvider="PreWarmMyCache" />
<!-- ... -->
</site>
3) ...and named said provider, with the GetType().AssemblyQualifiedName of the class listed in its entirety below
<serviceAutoStartProviders>
<add name="PreWarmMyCache" type="MyWCFServices.Preloader, HelloWorldServer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</serviceAutoStartProviders>
using System;
namespace MyWCFServices
{
public class Preloader : System.Web.Hosting.IProcessHostPreloadClient
{
public void Preload(string[] parameters)
{
System.IO.StreamWriter sw = new System.IO.StreamWriter(#"C:\temp\PreloadTest.txt");
sw.WriteLine("Preload executed {0:G}", DateTime.Now);
sw.Close();
}
}
}
Alas, all this manual configuration, plus a couple iisreset calls, and I get nothing. No w3wp.exe process firing up in Task Manager (though I get it if I launch the HelloWorldClient), no text file, and above all, no satisfaction.
There is a frustratingly scant amount of discussion about this feature, either on SO or the wider web, and the few similar questions here got little attention, all of which rings an alarm bell or two. Perhaps needlessly though--any experts out there who have been down this very road a time or two care to chime in? (Happy to offer up the entire solution if you can suggest a good place to host it.)
EDIT: I tried resetting that path in the Preload method to the relative App_Data folder (another SO answer suggested that), didn't matter. Also, I learned the w3wp.exe process fires on a simple browse to the localhost. The process consumes an impressive 17MB of memory to serve up its single tiny OperationContract, while for the price offering zero Preload value. 17MB of ColdDeadCache.
This is a slightly different approach for your problem:
Use Windows Server AppFabric for service auto-start
Use WCF infrastructure to execute custom startup code
Re 1: The Appfabric AutoStart feature should just work out of the box (provided you're not using MVC's ServiceRoute to register your services, they MUST be specified either in the Web.config's serviceActivations section or using physical *.svc files.
Re 2: To inject custom startup code into the WCF pipeline you could use an attribute like this:
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
namespace WCF.Extensions
{
/// <summary>
/// Allows to specify a static activation method to be called one the ServiceHost for this service has been opened.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
public class ServiceActivatorAttribute : Attribute, IServiceBehavior
{
/// <summary>
/// Initializes a new instance of the ServiceActivatorAttribute class.
/// </summary>
public ServiceActivatorAttribute(Type activatorType, string methodToCall)
{
if (activatorType == null) throw new ArgumentNullException("activatorType");
if (String.IsNullOrEmpty(methodToCall)) throw new ArgumentNullException("methodToCall");
ActivatorType = activatorType;
MethodToCall = methodToCall;
}
/// <summary>
/// The class containing the activation method.
/// </summary>
public Type ActivatorType { get; private set; }
/// <summary>
/// The name of the activation method. Must be 'public static void' and with no parameters.
/// </summary>
public string MethodToCall { get; private set; }
private System.Reflection.MethodInfo activationMethod;
#region IServiceBehavior
void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
serviceHostBase.Opened += (sender, e) =>
{
this.activationMethod.Invoke(null, null);
};
}
void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
// Validation: can get method
var method = ActivatorType.GetMethod(name: MethodToCall,
bindingAttr: System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public,
callConvention: System.Reflection.CallingConventions.Standard,
types: Type.EmptyTypes,
binder: null,
modifiers: null);
if (method == null)
throw new ServiceActivationException("The specified activation method does not exist or does not have a valid signature (must be public static).");
this.activationMethod = method;
}
#endregion
}
}
..which can be used like this:
public static class ServiceActivation
{
public static void OnServiceActivated()
{
// Your startup code here
}
}
[ServiceActivator(typeof(ServiceActivation), "OnServiceActivated")]
public class YourService : IYourServiceContract
{
}
That's the exact approach we've been using for quite a while and on a large number of services. The extra benefit of using a WCF ServiceBehavior for custom startup code (as opposed to relying on the IIS infrastructure) is that it works in any hosting environment (incl. self-hosted) and can be more easily tested.
I know this sounds absurd but I faced the same issue (w3wp.exe not firing automatically after making the config changes) and it was because I hadn't run the text editor in Admin mode when I was editing the applicationHost.config file. Stupid mistake on my part.
In my defense I was using Notepad++ which told me it was saving when it actually wasn't.
I've done the same. it works...
In preload method I have some code copied from a nice white paper available here!
Preload method looks like...
public void Preload(string[] parameters)
{
bool isServceActivated = false;
int attempts = 0;
while (!isServceActivated && (attempts <10))
{
Thread.Sleep(1 * 1000);
try
{
string virtualPath = "/Test1/Service1.svc";
ServiceHostingEnvironment.EnsureServiceAvailable(virtualPath);
isServceActivated = true;
}
catch (Exception exception)
{
attempts++;
//continue on these exceptions, otherwise fail fast
if (exception is EndpointNotFoundException ||
exception is ServiceActivationException ||
exception is ArgumentException)
{
//log
}
else
{
throw;
}
}
}
}
Maybe you are on a 64-bit system? There is a known "feature" in Windows where the save gets redirected to the 32 bit folder and thus no changes will be picked up
(I have converted my comment to an answer as answers might be easier to find)
I'm running two instances of my application. In one instance, I save one of my entities. When I check the RavenDB (http://localhost:8080/raven), I can see the change. Then, in my other client, I do this (below), but I don't see the changes from the other application. What do I need to do in order to get the most recent data in the DB?
public IEnumerable<CustomVariableGroup> GetAll()
{
return Session
.Query<CustomVariableGroup>()
.Customize(x => x.WaitForNonStaleResults());
}
Edit: The code above works if I try to make a change and get a concurrency exception. After that, when I call refresh (which invokes the above code), it works.
Here is the code that does the save:
public void Save<T>(T objectToSave)
{
Guid eTag = (Guid)Session.Advanced.GetEtagFor(objectToSave);
Session.Store(objectToSave, eTag);
Session.SaveChanges();
}
And here is the class that contains the Database and Session:
public abstract class DataAccessLayerBase
{
/// <summary>
/// Gets the database.
/// </summary>
protected static DocumentStore Database { get; private set; }
/// <summary>
/// Gets the session.
/// </summary>
protected static IDocumentSession Session { get; private set; }
static DataAccessLayerBase()
{
if (Database != null) { return; }
Database = GetDatabase();
Session = GetSession();
}
private static DocumentStore GetDatabase()
{
string databaseUrl = ConfigurationManager.AppSettings["databaseUrl"];
DocumentStore documentStore = new DocumentStore();
try
{
//documentStore.ConnectionStringName = "RavenDb"; // See app.config for why this is commented.
documentStore.Url = databaseUrl;
documentStore.Initialize();
}
catch
{
documentStore.Dispose();
throw;
}
return documentStore;
}
private static IDocumentSession GetSession()
{
IDocumentSession session = Database.OpenSession();
session.Advanced.UseOptimisticConcurrency = true;
return session;
}
}
Lacking more detailed information and some code, I can only guess...
Please make sure that you call .SaveChanges() on your session. Without explicitly specifiying an ITransaction your IDocumentSession will be isolated and transactional between it's opening and the call to .SaveChanges. Either all operations succeed or none. But if you don't call it all your previous .Store calls will be lost.
If I was wrong, please post more details about your code.
EDIT: Second answer (after additional information):
Your problem has to do with the way RavenDB caches on the client-side. RavenDB by default caches every GET request throughout a DocumentSession. Plain queries are just GET queries (and no, it has nothing to do wheter your index in dynamic or manually defined upfront) and therefore they will be cached. The solution in your application is to dispose the session and open a new one.
I suggest you rethink your Session lifecycle. It seems that your sessions live too long, otherwise this concurrency wouldn't be an issue. If you're building a web-application I recommend to open and close the session with the beginning and the end of your request. Have a look at RaccoonBlog to see it implemented elegantly.
Bob,
It looks like you have but a single session in the application, which isn't right. The following article talks about NHibernate, but the session management parts applies to RavenDB as well:
http://archive.msdn.microsoft.com/mag200912NHibernate
This code is meaningless:
Guid eTag = (Guid)Session.Advanced.GetEtagFor(objectToSave);
Session.Store(objectToSave, eTag);
It basically a no op, but one that looks important. You seems to be trying to work with a model where you have to manually manage all the saves, don't do that. You only need to manage things yourself when you create a new item, that is all.
As for the reason you get this problem, here is a sample:
var session = documentStore.OpenSession();
var post1 = session.Load<Post>(1);
// change the post by another client
post2 = session.Load<Post>(1); // will NOT go to the server, will give the same instance as post1
Assert.ReferenceEquals(post1,post2);
Sessions are short lived, and typically used in the scope of a single form / request.
I have an event receiver (WebAdding and WebProvisioned) which works just fine for sites created off the root of the site collection. However, subsites (for example, teamsites created within other areas) do not trigger the code at all.
Does anyone have any idea as to why?
using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
using System.Text;
namespace TestEventReceiver.EventReceiver1
{
/// <summary>
/// Web Events
/// </summary>
public class EventReceiver1 : SPWebEventReceiver
{
/// <summary>
/// A site is being provisioned.
/// </summary>
public override void WebAdding(SPWebEventProperties properties)
{
base.WebAdding(properties);
using (SPWeb web = properties.Web)
{
StringBuilder output = new StringBuilder();
output.AppendFormat("Web Adding");
output.AppendFormat("<br>Web title: {0}",web.Title);
SendMyEmail(web, "SendItToMe#MyTestAddress.com", "Web Adding", output.ToString());
}
}
/// <summary>
/// A site was provisioned.
/// </summary>
public override void WebProvisioned(SPWebEventProperties properties)
{
base.WebProvisioned(properties);
using (SPWeb web = properties.Web)
{
StringBuilder output = new StringBuilder();
output.AppendFormat("Web Provisioned");
output.AppendFormat("<br>Web title: {0}", web.Title);
SendMyEmail(web, "SendItToMe#MyTestAddress.com", "Web Provisioned", output.ToString());
}
}
private void SendMyEmail(SPWeb Web, String toAddress, String subject, String message)
{
bool appendHtmlTag = false;
bool htmlEncode = true;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPUtility.SendEmail(Web, appendHtmlTag, htmlEncode, toAddress, subject, message);
});
}
}
}
Thanks in advance,
Matt
I think you should not be using 'Using' .
The SPWeb object reference you get is from properties.Web which is being passed to the WebAdding method. You will run into issues because of this.
Have a look at how your event receiver is provisioned - it may be the scope needs to be changed to Site rather than Web. Perhaps you could post here so we can see.
On my site I had the same issue. Still figuring out the xml files, but in my Elements.xml file for the Receivers, each receiver had the same sequence number. Once I made them unique within the Elements.xml file, the WebProvisioned event started firing. Don't know if this is the same issue you were having.
This code is showing the WebAdding event and that event is occurring on the parent Web.
http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spwebeventreceiver.webadding.aspx
Try to change scope of your receiver (in Elements.xml file add attribute ). Also, make sure that the feature of your Event receiver is activated in you site features in the subsite.