Adding Dependency Injection to your ASP.NET MVC Twilio app using MEF (Managed Extensibility Framework)

Adding Dependency Injection to your ASP.NET MVC Twilio app using MEF (Managed Extensibility Framework)

http://www.twilio.com/blog/2012/11/adding-dependency-injection-to-your-asp-net-mvc-twilio-app-using-mef.html

Thanks for the Reblog Twilio!

TwilioCON 2012 Developer & Doers @ San Francisco, CA – Day 2

TwilioCON 2012 Hackathon was fun, teamed up with John Palmer @citriusjohn and kicked around a few ideas however figured it would be best if we waited for TwilioCON 2013 to actually compete.

It was great to finally meet some of the people I’ve done some work with remotely and/or through online meetings e.g. Evan Cummack (@cummack), Devin Rader (@devinrader), among other people at TwilioCON. Another highlight of the second day was hearing the good news that we are officially been approved to as an Authorized Twilio SI (Systems Integrator), thanks Greg, Cheetan, and the rest of Twilio’s SI division for making this happen. Wrapping up I had a blast, and hopefully we can do it again next year…!

TwilioCON 2012 Developer & Doers @ San Francisco, CA – Day 1

Had an awesome day yesterday @ TwilioCON 2012 here at San Francisco, CA. Attended some pretty interesting key notes and lab sessions. I really appreciate some of the new features added especially working with call queues (http://www.twilio.com/voice/features/queue) with Twilio Client (http://nuget.org/packages/Twilio.Client).

The demo of full browser soft phone was totally awesome, and having almost full Twilio Client ability on the client side as you would on the server side was also rocked! As day one of TwilioCon 2012 was wrapping up and I started packing, guess what?! Saw Scott Guthrie and fellows walk through the door, will keep you guys posted on what this is about in tomorrows blog, or you can keep an eye on my Twitter (http://twitter.com/lelong37) for updates on this.

Last but not least thanks for the Twilio VIP Dinner invite, had a blast!

Two-Factor Authentication ASP.NET MVC 4 Registration with Twilio SMS

Two-Factor Authentication ASP.NET MVC 4 Registration with Twilio SMS

http://www.twilio.com/blog/2012/10/multi-step-asp-net-mvc-4-registration-with-sms-using-twilio-cloud-communication-and-simplemembershipprovider-for-increased-user-validity.html

Thanks for the Reblog Twilio!

IoC, Dependency Injection, Manage Extensiblity Framework (MEF), ServiceLocator in .NET 4, MVC 4, WebApi, IDependencyResolver with Closed Types e.g. Twilio Types

Being accustomed to writing Mvc apps with IoC, specifically with Ninject and Managed Extensibility Framework (Mef), I wanted to see how we could inject most our Twilio instances (types TwilioResponse and the TwilioRestClient) when using them in my Mvc 4 WebApi Controller Actions.

To “Mefify” your Mvc 4 .NET 4.0 app, download the Mvc4.Mef project and reference this in your web app.

Let’s quickly review some of important classes in this project (Mvc.Mef) that do the heavy lifting to wire up Mef in your Mvc app.

  1. MefMvcConfig.cs

    • Creating our CompositionContainer, the container that holds all our exports and imports.
    • AggregateCatalog, which is a collection of catalogs, in our case composed of a ComposableCatalog (we pass in a TypeCatalog later from our our Mvc app, which inherits the Composable Catalog) and DirectoryCatalog which are of the possible classes that are decorated with [Export] and [Import] attributes from the current executing assembly as well as another other assemblies that maybe in the bin from our other projects.

    Note: The RegisterMef method will be invoked from your Application_Start(), Global.asax.cs class to wire integrate and wire up Mef into your Mvc app.

    
        public static class MefMvcConfig
        {
            public static void RegisterMef(TypeCatalog typeCatalog)
            {
                var compositionContainer = ConfigureContainer(typeCatalog);
                ServiceLocator
                    .SetLocatorProvider(() => new MefServiceLocator(compositionContainer));
    
                ControllerBuilder
                    .Current.SetControllerFactory(
                    new MefMvcControllerFactory(compositionContainer));
    
                GlobalConfiguration
                    .Configuration
                    .DependencyResolver = 
                    new MefMvcDependencyResolver(compositionContainer);
            }
    
            private static CompositionContainer ConfigureContainer(
                ComposablePartCatalog composablePartCatalog)
            {
                var path = HostingEnvironment.MapPath("~/bin");
                if (path == null) throw new Exception("Unable to find the path");
    
                var aggregateCatalog = new AggregateCatalog(new DirectoryCatalog(path));
    
                if (composablePartCatalog != null)
                    aggregateCatalog.Catalogs.Add(composablePartCatalog);
    
                return new CompositionContainer(
                    aggregateCatalog,
                    new MefNameValueCollectionExportProvider(
                        ConfigurationManager.AppSettings));
            }
        }
    
  2. MefMvcControllerFactory.cs, which inherits the Overriding and setting the default Mvc ControllerFactory with our own that we use our DefaultControllerFactory, the MefMvcControllerFactory is used to scan our CompositionContainer when attempting to resolve Controller types.
    
        public class MefMvcControllerFactory : DefaultControllerFactory
        {
            private readonly CompositionContainer _compositionContainer;
    
            public MefMvcControllerFactory(CompositionContainer compositionContainer)
            {
                _compositionContainer = compositionContainer;
            }
    
            protected override IController GetControllerInstance(
                RequestContext requestContext, Type controllerType)
            {
                var export = _compositionContainer
                    .GetExports(controllerType, null, null).SingleOrDefault();
    
                IController result;
    
                if (null != export)
                    result = export.Value as IController;
                else
                {
                    result = base.GetControllerInstance(requestContext, controllerType);
                    _compositionContainer.ComposeParts(result);
                }
    
                return result;
            }
    
    
    
  3. MefMvcDependencyResolver.cs, which is used, when we override and the default Mvc DependencyResolver, so that when there are dependencies in our WebApi Controllers, the Mvc runtime will use our own MefMvcDependencyResolver to resolve those dependencies
    
        public class MefMvcDependencyResolver : IDependencyResolver
        {
            private readonly CompositionContainer _compositionContainer;
    
            public MefMvcDependencyResolver(CompositionContainer compositionContainer)
            {
                _compositionContainer = compositionContainer;
            }
    
            #region IDependencyResolver Members
    
            public IDependencyScope BeginScope()
            {
                return this;
            }
    
            public object GetService(Type type)
            {
                var export = _compositionContainer
                    .GetExports(type, null, null).SingleOrDefault();
    
                return null != export ? export.Value : null;
            }
    
            public IEnumerable<object> GetServices(Type type)
            {
                var exports = _compositionContainer.GetExports(type, null, null);
                var exportList = new List<object>();
                if (exports.Any()) exportList.AddRange(exports.Select(export => export.Value));
                return exportList;
            }
    
            public void Dispose()
            {
            }
    
            #endregion
        }
    
    
    
  4. MefNameValueCollectionExportProvider.cs, which enables us to load in to our CompositionContainer our Web.config AppSettings key and values in the case we want to resolve them with injection e.g. Twilio AccountSid and AuthoToken from our Web.config AppSettings.
    
        public class MefNameValueCollectionExportProvider : ExportProvider
        {
            private readonly List<Export> _exports;
    
            public MefNameValueCollectionExportProvider(NameValueCollection settings)
            {
                _exports = new List<Export>();
    
                foreach (string key in settings)
                {
                    var metadata = new Dictionary<string, object> {
                        {
                            CompositionConstants
                            .ExportTypeIdentityMetadataName, typeof (string)
                            .FullName
                        }};
    
                    var exportDefinition = new ExportDefinition(key, metadata);
    
                    _exports.Add(new Export(exportDefinition, () => settings[key]));
                }
            }
    
            protected override IEnumerable<Export> GetExportsCore(
                ImportDefinition importDefinition, AtomicComposition atomicComposition)
            {
                return _exports
                    .Where(x => importDefinition.IsConstraintSatisfiedBy(x.Definition));
            }
        }
    
    
  5. MefAdapter.cs, which is based from Mark Seemaan’s blog on Resolving Close Types with Mef, this class will be used so that we can add close classes/objects, which we cannot annotate with the [Export] and/or [Import] attributes, in this example I will demonstrate this with Twilio’s objects.

    
        public class MefAdapter<T> where T : new()
        {
            private readonly T _typeToExport;
    
            public MefAdapter()
            {
                _typeToExport = new T();
            }
    
            [Export]
            public virtual T TypeToExport
            {
                get { return _typeToExport; }
            }
        }
    
        public class MefAdapter<T1, T2, TResult>
        {
            private static readonly Func<T1, T2, TResult> 
                CreateExport = Create<T1, T2, TResult>();
    
            private readonly TResult _typeToExport;
    
            [ImportingConstructor]
            public MefAdapter(T1 arg1, T2 arg2)
            {
                _typeToExport = CreateExport(arg1, arg2);
            }
    
            [Export]
            public virtual TResult TypeToExport
            {
                get { return _typeToExport; }
            }
    
            internal static Func<T1, T2, TResult> Create<T1, T2, TResult>()
            {
                var constructorArgExpression1 = Expression.Parameter(typeof (T1), "arg1");
                var constructorArgExpression2 = Expression.Parameter(typeof (T2), "arg2");
    
                var constructorInfo = typeof (TResult).GetConstructor(new[]
                        {
                            typeof (T1),
                            typeof (T2)
                        });
    
                var constructorExpression = Expression
                    .New(constructorInfo, constructorArgExpression1, constructorArgExpression2);
    
                return Expression.Lambda<Func<T1, T2, TResult>>(
                    constructorExpression, 
                    constructorArgExpression1, 
                    constructorArgExpression2)
                    .Compile();
            }
        }
    

Now switching to your Mvc 4 app, here are the simple steps to wire this up, first few steps is to simply NuGet CommonServiceLocator, using this we obviously will also be practicing the ServiceLocator Pattern.

Now, download the Mvc4.Mef.Framework project, and reference it in your MVC 4 application and add one line to your Global.asax.cs file to get this all setup. Since we are here let’s go ahead and add some UriPathExtensionMapping configurations so that we can serve up some real Twilio request later on to demonstrate Dependency Injection with the TwilioRequest object from their Api, these UriPathExtensionMappings are not required for Mef’ing your Mvc app.

Note: notice that we are passing in a TypeCatalog when we invoke the RegisterMef method, this is so that we can pass in closed classes (types) that we would like to inject or resolve with Dependency Injection using Mef in this case the TwilioResponse object from their Api.

Global.asax.cs


    public class MvcApplication : HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            MefMvcConfig.RegisterMef(new TypeCatalog(typeof(MefAdapter<TwilioResponse>)));

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            GlobalConfiguration
                .Configuration.Formatters
                .XmlFormatter
                .AddUriPathExtensionMapping("xml", "text/xml");

            GlobalConfiguration
                .Configuration
                .Formatters
                .XmlFormatter
                .AddUriPathExtensionMapping("json", "application/json");
        }
    }

Now if we run our app you should see that the request from the HomeController is now getting resolved through our MefMvcControllerFactory from our CompositionContainer. In this screenshot, I’ve pinned the watch to source (Visual Studio 2012) to illustrate that the Controller type that is being succesfully resolved with DependencyInjection is indeed the HomeController.

In order for Mef to serve up and resolve these Controllers we have to decorate our controllers with the [Export] attribute e.g. HomeController.

Note: The [PartCreationPolicy(CreationPolicy.NonShared)], means that whenever this instance is requested, Mef will new up (instantiate) a new instance every time, the opposite would be CreationPolicy.Shared, which will new one up the first time and keep it alive, and serve this same instance, every time it is requested (which is the behavior we don’t want for Mvc Controllers).


    [Export]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = 
                "Modify this template to jump-start your ASP.NET MVC application.";

            return View();
        }

        public ActionResult About()
        {
            ViewBag.Message = "Your app description page.";

            return View();
        }

        public ActionResult Contact()
        {
            ViewBag.Message = "Your contact page.";

            return View();
        }
    }
}

Now for the fun part, this Mvc 4 project is from one of my previous blogs Multi-Step (Two-Factor) ASP.NET MVC 4 Registration with SMS using Twilio Cloud Communication and SimpleMembershipProvider for Increased User Validity, where we were using TwilioRestClient from their Api to send SMS messages for Two-Factor registration. Let’s see how we can inject this now with Mef in our Register Action.

Before:


        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                try
                {
                    var smsVerificationCode =
                        GenerateSimpleSmsVerificationCode();

                    WebSecurity.CreateUserAndAccount(
                        model.UserName,
                        model.Password,
                        new
                            {
                                model.Mobile,
                                IsSmsVerified = false,
                                SmsVerificationCode = smsVerificationCode
                            },
                        true);

                    var twilioRestClient = new TwilioRestClient(
                        ConfigurationManager.AppSettings.Get("Twilio:AccoundSid"),
                        ConfigurationManager.AppSettings.Get("Twilio:AuthToken"));

                    twilioRestClient.SendSmsMessage(
                        "+19722001298",
                        model.Mobile,
                        string.Format(
                            "Your ASP.NET MVC 4 with Twilio " +
                            "registration verification code is: {0}",
                            smsVerificationCode)
                        );

                    Session["registrationModel"] = model;

                    return RedirectToAction("SmsVerification", "Account", model);
                }
                catch (MembershipCreateUserException e)
                {
                    ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

After:


        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                try
                {
                    var smsVerificationCode =
                        GenerateSimpleSmsVerificationCode();

                    WebSecurity.CreateUserAndAccount(
                        model.UserName,
                        model.Password,
                        new
                            {
                                model.Mobile,
                                IsSmsVerified = false,
                                SmsVerificationCode = smsVerificationCode
                            },
                        true);

                    var twilioRestClient = ServiceLocator.Current.GetInstance<TwilioRestClient>();

                    twilioRestClient.SendSmsMessage(
                        "+19722001298",
                        model.Mobile,
                        string.Format(
                            "Your ASP.NET MVC 4 with Twilio " +
                            "registration verification code is: {0}",
                            smsVerificationCode)
                        );

                    Session["registrationModel"] = model;

                    return RedirectToAction("SmsVerification", "Account", model);
                }
                catch (MembershipCreateUserException e)
                {
                    ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

Notice in line 25, we are now using ServiceLocator to resolve the dependency in our Register action for the TwilioRestClient. Here Mef will take care of activating and setting up our TwilioRestClient instance for us.

Ideally we would want to wrap (Composition Pattern) the TwilioRestClient, implementing our own interface and injecting the interface with our wrapped TWilioRestClient. If time permits, I’ll cover this in another post, for now we’ll just have fun with injecting closed classes with Mef.

Let’s see the TwilioRestClient injection with ServiceLocator in action by running the app and registering.

Register View

Debugging in our Register Action from the AccountController, notice how our TwilioRestClient is successfully being activated, injected and resolved with the ServiceLocator, which really is just scanning our CompositionContainer we had setup earlier, which was made possible with our TwilioRestClientMefAdapter.

Great! We received a test SMS text message with our injected TwilioRestClient.

How did this happen? Will we had to create a TwilioRestClientMefAdapter (this is a variation of the Adapter Pattern) class, this was needed because the TwilioRestClient does not have parameterless constructor, and those parameters were our Twilio AccountSid and AuthToken which were in our Web.config.


    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class TwilioRestClientMefAdapter
    {
        private readonly TwilioRestClient _twilioRestClient;

        [ImportingConstructor]
        public TwilioRestClientMefAdapter(
            [Import("Twilio:AccoundSid")] string accountSid,
            [Import("Twilio:AuthToken")] string authToken)
        {
            _twilioRestClient = new TwilioRestClient(accountSid, authToken);
        }

        [Export]
        public TwilioRestClient TwilioRestClient
        {
            get { return _twilioRestClient; }
        }
    }

Let’s debug the activation process, just to understand what’s happening here.

Now, when we inject our TwilioRestClient with


var twilioRestClient = ServiceLocator.Current.GetInstance<TwilioRestClient>();

what’s happening is that, what’s marked for Export is the property named TwilioRestClient. In order for Mef to export that property it must instantiate the class that it lives in which in our case is the TwilioRestClientMefAdapter class. The constructor marked with [ImportingConstructor] is what Mef will scan for, to activate this class. In the constructor is where we are also injecting our AccountSid and AuthToken from our web.conf appSettings that was loaded earlier into our CompositionContainer using our MefNameValueCollectionExportProvider.cs class, where we passed in ConfigurationManager.AppSettings to our MefMvcConfig.ConfigureContainer method. Fortunately for us, the ConfigurationManager.AppSettings happens to be a NameValueCollection.


        private static CompositionContainer ConfigureContainer(
            ComposablePartCatalog composablePartCatalog)
        {
            var path = HostingEnvironment.MapPath("~/bin");
            if (path == null) throw new Exception("Unable to find the path");

            var aggregateCatalog = new AggregateCatalog(new DirectoryCatalog(path));

            if (composablePartCatalog != null)
                aggregateCatalog.Catalogs.Add(composablePartCatalog);

            return new CompositionContainer(
                aggregateCatalog,
                new MefNameValueCollectionExportProvider(
                    ConfigurationManager.AppSettings));
        }


Now, one more injection test with the TwilioResponse object, which is probably used most when developing with Twilio Cloud. We will test our WeatherController, which is pretty much a voice caller, calling in, being prompt to enter in their zip code and our our application telling the user what the weather is like for their zip. For this test we will need the Curl command line utility since it’s a WebApi method that will be invoked via a POST.

Let’s run, our app and test the pseudo WeatherController which we use an injected instance of the TwilioResponse. For this test, we will use the [Import] attribute to inject and activate our TwilioResponse vs. using the ServiceLocator. There’s no wrong or right way to get our instances activated, this is just preference.

Now lets run this command with Curl.

curl http://localhost:64190/api/weather/gatherzipcode.xml -X POST -d “fro
m=123”

With breakpoints setup, we can see that our TwilioResponse is being successfully activated and injected into our WeatherController using the [Import] attribute!

Our WebApi returns the required TwiML response.


<Response><Gather action="http://myapp.com/api/Weather/RetrieveWeather.xml" finishOnKey="#"><Say voice="woman">Please en
ter the zip code of the area you would like the weather in.</Say></Gather><Gather action="http://myapp.com/api/Weather/R
etrieveWeather.xml" finishOnKey="#"><Say voice="woman">Please enter the zip code of the area you would like the weather
in.</Say></Gather></Response>

How did our TwilioResponse object get resolved, activated and injected into our WeatherController? Well when we registered the Mef framework in our Global.asax.cs with:


MefMvcConfig.RegisterMef(new TypeCatalog(typeof(MefAdapter<TwilioResponse>)));

We passed in a TypeCatalog, and we initialized the TypeCatalog, passing in a list of types, in our case we are passing in our MefAdapter, that is used for the TwilioResponse type. This is because the TwilioResponse object is a closed object that we have no control over, and cannot decorate the class with any [Export] attributes.

Now let’s take a quick look at the internals of the MefAdapter, to understand how this is happening, it’s behavior is pretty similar to our TwilioRestClientAdapter we implemented earlier.


    public class MefAdapter<T> where T : new()
    {
        private readonly T _typeToExport;

        public MefAdapter()
        {
            _typeToExport = new T();
        }

        [Export]
        public virtual T TypeToExport
        {
            get { return _typeToExport; }
        }
    }

When we pass in the MefAdapter to our TypeCatalog, and we request an instance of T, Mef will new up our MefAdapter, by default use the parameterless constructor, which will new up an instance of T (which is TwilioResponse in our case), and now the TwilioResponse is initialized and passed back to our WeatherController.

Well, there we have it, integrating Mef into our .NET 4 Mvc 4 project, and injecting closed objects which we are unable to attribute with [Export] and/or [Import] attributes with our Mef adapters.

Happy Coding…! 🙂

Download sample solution: https://skydrive.live.com/redir?resid=949A1C97C2A17906!2391

Developing with Twilio Cloud Communication using MVC 4, WebApi and UriPathExtensionMapping Configurations

Twilio has some pretty good documentation on developing with MVC using your traditional Controllers, Actions, and Views leveraging their REST Api’s. However this post will be for those that would like to develop around Twilio this using MVC’s new WebApi.

There are typically no Views being used when working with Twilio’s Platform (unless you are placing in-line code in your View’s markup), it’s largely a lot of REST like request’s that Twilio makes to your application and your application is responding with XML payloads, so that Twilio can injest your Xml payload and figure out what the next step is, whether it be a voice and/or SMS request.

So let’s get into it, the first thing we do is to get our MVC 4 app infrastructure ready.

In Global.asax.cs, let’s add some Uri path extensions, meaning our WebApi methods will know what type of content/type to deliver back from a request by the extension of the Url. For example if we have a inbound request for a collection of some sort mapped to http://localhost/api/MyController/MyPost.xml, the MVC runtime will know to return my collection in Xml vs. Json (MediaTypeFormatterExtensions.AddUriPathExtensionMapping).


    public class WebApiApplication : HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            MefConfig.RegisterMef();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            FilterConfig.RegisterHttpFilters(GlobalConfiguration.Configuration.Filters);
            MapperConfig.RegisterMappings();

            GlobalConfiguration
                .Configuration
                .Formatters
                .XmlFormatter
                .AddUriPathExtensionMapping("xml", "text/xml");

            GlobalConfiguration
                .Configuration
                .Formatters
                .XmlFormatter
                .AddUriPathExtensionMapping("json", "application/json");
        }
    }

Note: Technically, we only need the UriPathExtensionMapping for Xml, however just in case we ever decided to still want to serve up Json payloads from our WebApi methods we will go ahead and add one for Json as well. That way our Api methods can return either Xml or Json just by changing the extension on the url.

For example:

Update and/or add a WebApi route (in this case I’ll just replace the one that’s there since I don’t need the default route at all) so that we can support our added UriPathExtensionMappings we added earlier (.xml, .json).

Location: YourMvc4Project/App_Start/WebApiConfig.cs


    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "Api with action and extension ",
                routeTemplate: "api/{controller}/{action}.{ext}/{id}",
                defaults: new {
                    id = RouteParameter.Optional, 
                    ext = RouteParameter.Optional}
                );

            //config.Routes.MapHttpRoute(
            //    name: "DefaultApi",
            //    routeTemplate: "api/{controller}/{id}",
            //    defaults: new {id = RouteParameter.Optional}
            //    );
        }
    }


Now we can build a fictitious example of a Weather WebApi controller for Twilio to make requests to.

  • GatherZipCode method, will prompt a a voice caller for what zip code the caller is interested for weather information.
  • RetrieveWeather method, will actually read and speak the weather condition to the voice caller, obviously this is a an example and you would probably need to hit a real weather service such as Accuweather for real world purposes.
  • I prefer implementing it this way, because at the end of the day you end up with just small methods that handle responses to Twilio requests, and we get to use the TwilioResponse object to give us some assistance in what we are trying to send back to Twilio. With this being said we don’t have to worry about stringing together Xml string(s) in our code, the TwilioReponse object has a handy property named Element (twilioResponse.Element) that handles nice serialization for us, and provding a representation of of the object in Xml that is Twilio ready for us to send back.

     
    
        public class WeatherController : ApiController
        {
            public HttpResponseMessage GatherZipCode(TwilioRequest twilioRequest)
            {
                var twilioResponse = new TwilioResponse();
    
                twilioResponse.BeginGather(
                    new 
                    {
                        action = "http://myapp.com/api/Weather/RetrieveWeather.xml", 
                        finishOnKey = "#"
                    });
    
                twilioResponse.Say(
                    "Please enter the zip code of the area you would like the weather in.", 
                    new {voice = "woman"});
    
                twilioResponse.EndGather();
    
                return Request.CreateResponse(HttpStatusCode.OK, twilioResponse.Element);
            }
    
            public HttpResponseMessage RetrieveWeather(TwilioRequest twilioRequest)
            {
                var zipcode = twilioRequest.Digits;
    
                var zipWeather = new Dictionary<string, string>
                    {
                        {"75042", "sunny"},
                        {"75043", "rainy"},
                        {"75044", "windy"},
                        {"75045", "thunder storms"}
                    };
    
                var twilioResponse = new TwilioResponse();
    
                twilioResponse.Say(
                    string.Format(
                        "The weather conditions in your zip code is {0}", 
                        zipWeather[zipcode]), new {voice = "woman"});
    
                return Request.CreateResponse(HttpStatusCode.OK, twilioResponse.Element);
            }
        }
    

    Great, now how can we do some level of testing with our Twilio ready WebApi’s locally? Meaning let’s do some level of testing before we involve actual people and their actual phones and/or Skype accounts.

    You will need to download the Curl utility (http://curl.haxx.se/download.html).

    Run your application, and issue a couple of command to invoke your new WebApi methods and make sure they are returning the correct Xml payloads to Twilio, you can cross reference your Xml payloads with Twilio TwiML Referenence (http://www.twilio.com/docs/api/twiml).

    Go ahead and spin up command prompt and navigate to the Curl command line utility, now let’s run a couple of commands to inspect the Xml payloads we are expecting to return to Twilio.

    curl http://localhost:64190/api/weather/gatherzipcode.xml -X POST

    Now when we execute this command we get:

    
    <Response><Gather action="http://myapp.com/api/Weather/RetrieveWeather.xml" finishOnKey="#"><Say voice="woman">Please en
    ter the zip code of the area you would like the weather in.</Say></Gather></Response>
    
    

    Now we can cross reference and compare it with when reviewing the “Say” verb from Twilio TwiML docs on how to use the “Say” verb (http://www.twilio.com/docs/api/twiml/say) to get some level of comfort that we are returning the right Xml payloads from our WebApi methods before actually getting people and phones in the picture.

    The next step, if your developing locally, and if you are developing on a workstation that is not publicy exposed to the internet, an option for you could be leveraging Windows Azure Service Bus for it’s relaying features. The Windows Azure Service Bus relaying pattern is pretty much the same pattern used for services that are in cloud that need to work with services that are on-premise that are deep inside a company’s infrastructure behind their firewall.

    You can visit Devin’s blog http://www.twilio.com/blog/2012/06/relaying-twilio-requests-using-windows-azure.html to set up relaying with Windows Azure Service Bus for Twilio development.

Multi-Step (Two-Factor) ASP.NET MVC 4 Registration with SMS using Twilio Cloud Communication and SimpleMembershipProvider for Increased User Validity

Some sites such as live.com, gmail.com will require a multi-step registration and/or forgot password workflows to validate you say you are. Having an opportunity working with the Twilio Cloud Communication Platform, exposed how easily this can be done with their Api’s.

So for this post, I wanted to illustrate the steps in getting your MVC 4 application wired up with multi-step registration process with SMS code verification leveraging Twilio. We will start from my last blog post with Seed Users and Roles with MVC 4, SimpleMembershipProvider, SimpleRoleProvider, EntityFramework 5 CodeFirst, and Custom User Properties.

Since we already gathered the user’s mobile number during registration, let’s go ahead and add a property/field “IsSmsVerified” and run EntityFramework’s migration command update-database -verbose (so we can see what commands are being issued to our database for the migration.

NuGet and install the Twilio.Mvc package.

Update our UserProfile entity with IsSmsVerified and SmsVerificationCode properties.


    [Table("UserProfile")]
    public class UserProfile
    {
        public UserProfile()
        {
            IsSmsVerified = false;
        }

        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int UserId { get; set; }
        public string UserName { get; set; }
        public string Mobile { get; set; }
        [DefaultValue(false)]
        public bool IsSmsVerified { get; set; }
        public string SmsVerificationCode { get; set; }
    }

Update our Seed method so that we are not inserting nulls for the provisioned users.


#region

using System.Data.Entity.Migrations;
using System.Linq;
using System.Web.Security;
using MVC4SimpleMembershipCodeFirstSeedingEF5.Models;
using WebMatrix.WebData;

#endregion

namespace MVC4SimpleMembershipCodeFirstSeedingEF5.Migrations
{
    internal sealed class Configuration : DbMigrationsConfiguration<UsersContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = true;
        }

        protected override void Seed(UsersContext context)
        {
            WebSecurity.InitializeDatabaseConnection(
                "DefaultConnection",
                "UserProfile",
                "UserId",
                "UserName", autoCreateTables: true);

            if (!Roles.RoleExists("Administrator"))
                Roles.CreateRole("Administrator");

            if (!WebSecurity.UserExists("lelong37"))
                WebSecurity.CreateUserAndAccount(
                    "lelong37",
                    "password",
                    new {Mobile = "+19725000374", IsSmsVerified = false});

            if (!Roles.GetRolesForUser("lelong37").Contains("Administrator"))
                Roles.AddUsersToRoles(new[] {"lelong37"}, new[] {"Administrator"});
        }
    }
}

Run: update-database -verbose from the Package Manager Console

Now the fun begins, let’s update our AccountController.

  • Update the Register(RegisterModel model) Action and introduce the second step registration process of entering an SMS verfication code that we send the user using Twilio’s REST Api Client.

    Note: We are just scratching the tip of the ice berg in terms of what the Twilio Cloud Communication offers, you can visit their docs site for more info.

  • Add SmsVerification() Action, so that the user can enter the SMS verification code.
  • Add SmsVerication(SmsVerificationModel smsVerificationModel) Action, so that we can validate the user, the user’s mobile number, and SMS verification code.
  • Add GenerateSimpleSmsVerificationCode() method, a simple static helper method to generate a six character SMS verification code.

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                try
                {
                    var smsVerificationCode =
                        GenerateSimpleSmsVerificationCode();

                    WebSecurity.CreateUserAndAccount(
                        model.UserName,
                        model.Password,
                        new
                            {
                                model.Mobile,
                                IsSmsVerified = false,
                                SmsVerificationCode = smsVerificationCode
                            },
                        false);

                    var twilioRestClient = new TwilioRestClient(
                        ConfigurationManager.AppSettings.Get("Twilio:AccoundSid"),
                        ConfigurationManager.AppSettings.Get("Twilio:AuthToken"));

                    twilioRestClient.SendSmsMessage(
                        "+19722001298",
                        model.Mobile,
                        string.Format(
                            "Your ASP.NET MVC 4 with Twilio " +
                            "registration verification code is: {0}",
                            smsVerificationCode)
                        );

                    Session["registrationModel"] = model;

                    return RedirectToAction("SmsVerification", "Account");
                }
                catch (MembershipCreateUserException e)
                {
                    ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        [AllowAnonymous]
        public ActionResult SmsVerification()
        {
            return View(new SmsVerificationModel
                {
                    Username =
                        ((RegisterModel) Session["registrationModel"])
                            .UserName
                });
        }

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult SmsVerification(SmsVerificationModel smsVerificationModel)
        {
            if (ModelState.IsValid)
            {
                var userContext = new UsersContext();

                var userProfile = userContext.UserProfiles
                    .Single(u => u.UserName == smsVerificationModel.Username);

                var registerModel = ((RegisterModel) Session["registrationModel"]);

                if (userProfile.SmsVerificationCode == smsVerificationModel.SmsVerificationCode)
                {
                    WebSecurity.Login(userProfile.UserName, registerModel.Password);
                    return RedirectToAction("Index", "Home");
                }
            }

            ModelState.AddModelError("", "The SMS verfication code was incorrect.");
            return RedirectToAction("SmsVerification", "Account");
        }

        private static string GenerateSimpleSmsVerificationCode()
        {
            const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            var random = new Random();
            return new string(
                Enumerable.Repeat(chars, 6)
                    .Select(s => s[random.Next(s.Length)])
                    .ToArray());
        }

We could combine the two actions SmsVerication() and SmsVerication(SmsVerificationModel smsVerificationModel) into one, by checking the request verb for GET or Post, however for separation of concerns we will keep them “nice” and “separate”.

Let’s add some AppSettings entries to store our Twilio Rest Api credentials.


  <appSettings>
    <add key="webpages:Version" value="2.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="PreserveLoginUrl" value="true" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
    <add key="Twilio:AccoundSid" value="youtwilioaccountid" />
    <add key="Twilio:AuthToken" value="yourtwilioauthtoken" />
  </appSettings>

Note: Your Twilio credentials for using their REST Api can be found on your dashboard after registering.

Create a SmsVerification ViewModel.


using System.ComponentModel.DataAnnotations;

using System.ComponentModel.DataAnnotations;

namespace MVC4SimpleMembershipCodeFirstSeedingEF5.Models
{
    public class SmsVerificationModel
    {
        [Display(Name = "Username")]
        public string Username { get; set; }

        [Required]
        [Display(Name = "SMS Verification Code")]
        public string SmsVerificationCode { get; set; }
    }
}

Let’s create the SmsVerification View where a user can input the SMS verification code that we sent to the user bound to the ViewModel we just created.

@model MVC4SimpleMembershipCodeFirstSeedingEF5.Models.SmsVerificationModel
@{
    //ViewBag.Title = "SMS Verification with MVC 4 & Twilio";
    ViewBag.Title = "SmsVerification";
}

<hgroup class="title">
    <h1>@ViewBag.Title.<br/></h1>
    <h3>Please enter your SMS verification code to complete registration.</h3>
</hgroup>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()

    @Html.HiddenFor(m => m.Username)

    <fieldset>
        <legend>SMS Verifcation Form</legend>
        <ol>
            <li>
                @Html.LabelFor(m => m.Username)
                @Html.DisplayTextFor(m => m.Username) 
                <br/><br/>
            </li>
            <li>
                @Html.LabelFor(m => m.SmsVerificationCode)
                @Html.TextBoxFor(m => m.SmsVerificationCode)
            </li>
        </ol>
        <input type="submit" value="SmsVerification" />
    </fieldset>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Step 1 of the registration process, run the application and register.

For a quick sanity check let’s just make sure our SimpleMembershipProvider is persisting the extra properties we added earlier e.g. SmsVerificationCode, IsSmsVerified.


SELECT TOP 1000 [UserId]
      ,[UserName]
      ,[Mobile]
      ,[IsSmsVerified]
      ,[SmsVerificationCode]
  FROM [aspnet-MVC4SimpleMembershipCodeFirstSeedingEF5].[dbo].[UserProfile]

Good, we can see here that Mobile, IsSmsVerified and SmsVerificationCode is being saved when we invoked the WebSecurity.CreateUserAndAccount method earlier from our Registration Action.


                    WebSecurity.CreateUserAndAccount(
                        model.UserName,
                        model.Password,
                        new
                            {
                                model.Mobile,
                                IsSmsVerified = false,
                                SmsVerificationCode = smsVerificationCode
                            },
                        false);

Step 2, SMS notification to the user’s mobile number was received with the SMS verification code.

Step 3 of the registration process, input the SMS verification code in the SMSVerfication View.

You have now successfully completed the 3 step registration process and have been automatically logged into the site!

Now there are obviously TODO’s here, you can create an new authorize Attribute to verify that the IsSmsVerified property for the user is not false, clean up how we are storing the RegisterModel in session, additional bullet proofing the app in terms of security gaps, etc.. However the emphasis of this blog was multi-step registration to for increased validity of the user.

Last but not least, you can use the a similar implementation for things like forgot password or any other type of workflow that needs that extra degree of validation.

Happy Coding…! 🙂

Download sample application: https://skydrive.live.com/redir?resid=949A1C97C2A17906!2383