ASP.NET MVC

Status of SimpleMembership.Mvc3 and SimpleMembership.Mvc3.Sample

I have received a couple of questions and requests over the past 6 months or so regarding my plans to update both the SimpleMembership.Mvc3 and SimpleMembership.Mvc3.Sample packages.

In short, I’m planning on updating these but I just haven’t gotten to it yet. I’ve been very busy lately with some other projects such as Expansive and my C# wrapper for the DNSimple REST API.

However, in preparation for these changes I have started a Trello board here: https://trello.com/board/simplemembership/4f23419c0fa7e50d34585d9e

I’m using this to track requests I have received and to communicate the status of the features that have been requested.

Please feel free to comment on them or vote or request new features.

However, these being open source projects on GitHub, please also feel free to fork them, add your desired features and submit a pull request to me to merge your changes back into the trunk.

Both projects can be found on GitHub using the following links:

I am going to try to get these changes done soon, but I just haven’t been able to dedicate any time to them yet.

In the meantime, thanks again for your interest, feedback, questions and requests regarding SimpleMembership.

Stay tuned…

Expansive 1.5 Released

Yesterday, I blogged about my new .NET string expansion library called Expansive.

Today, I made some key changes to, hopefully, make it easier to use and more flexible by providing 4 token style format providers out of the box.

  • Removed the startToken and endToken delimiters that could be set by the consumer as this was unreliable
  • Added 4 new Token Style Formats to pick from:
    • MvcRoute Style “{token}” (default)
    • Razor Style “@token” or “@(token)”
    • NAnt Style “${token}”
    • MSBuild Style “$(token)”

So, the following are all valid:

// MvcRoute-Style (default)
var mvcRouteStyleString = "Hello, {FirstName}".Expand(new { FirstName = "John" });

// Razor-Style
Expansive.DefaultTokenStyle = TokenStyle.Razor;
var razorStyleString = "Hello, @FirstName".Expand(new { FirstName = "John" });

// NAnt-Style
Expansive.DefaultTokenStyle = TokenStyle.NAnt;
var nantStyleString = "Hello, ${FirstName}".Expand(new { FirstName = "John" });

// MSBuild-Style
Expansive.DefaultTokenStyle = TokenStyle.MSBuild;
var msBuildStyleString = "Hello, $(FirstName)".Expand(new { FirstName = "John" });

// all return "Hello, John"

You can also specify the TokenStyle on the call to Expand() such as:

var expandedString = "Hello, @FirstName".Expand(new { FirstName = "John" }, TokenStyle.Razor);

The addition of TokenStyle makes the API a little cleaner and provide 4 popular token formats.

You can of course add your own by grabbing the source on GitHub and opening the hood.

Enjoy!

Expansive – A powerful string expansion library for .NET you never knew you always wanted.

Expansive

  1. having a capacity or tendency to expand.
  2. causing or tending to cause expansion
  3. characterized by richness, abundance or magnificence

While working on a recent project involving lots of appSettings keys and values in my web.config/app.config files and some values that have overlapping information (server names, file paths, etc.), I realized how much I missed the property expansion capabilities of NAnt and, more recently, MSBuild. So, I set out to see if I could quickly build a simple string property expansion library to solve this common problem and maybe some others along the way.

While I knew that true string interpolation would be somewhat tricky and probably best left to the framework developers, I felt that an easy add-on API using extension methods and possibly some new helper classes could at least make my life easier.

Channeling Rob Conery, I named my new library Expansive as a play on Expansion and Expensive (sarcasm) as I wanted something that wasn’t expensive (technically) and was easy to implement and easy to learn.

You can check out the full capabilities via the readme over on GitHub, but I’ll give you a couple of examples and ideas on how it can be used.

1. Solve web.config / app.config nightmares

Many times I find that in large applications, I have many web.config / app.config appSettings keys, connection strings, etc and that many of the values have redundant information. For instance server names, IP Addresses or paths may be strewn throughout several appSettings keys and I find myself wishing I could just define the data once, so as to “normalize” my appSettings, and then simply reference one key from the value of another. What I really want is a composition model where I can compose different appSettings (or other strings for that matter) using previously defined values.

Here’s a common scenario:

  • I may have a connection string defined with a server name: dbserver01
  • I may have environment specific naming conventions like (dbserver01-dev, dbserver01-qa, dbserver01-stg, dbserver01-prod, etc)
  • I may have other server names in my appSettings like urls for services, unc paths for fileshares, report server urls, etc.
  • While I can certainly duplicate the server names and environment suffix throughout the various appSettings keys, it quickly becomes a chore to make sure these are all correct for a specific environment.
  • Web.config transforms help a little bit in that they allow me to define values for different configurations, but it still doesn’t give me a composition model where I can simplify my web.config / app.config settings so that they are easier to manage and maintain. Plus web.config transforms only help at build/deploy time. There is no story for runtime changes.

Expansive aims to solve that problem by allowing for NAnt-like property expansion (scroll down to section 6) whereby I can define an appSetting once such as:

<add key="env" value="dev"/>

And then be able to reuse that value in other settings such as:

<add key="ServerName" value="dbserver01-{env}"/>

And, then finally use that value inside of a connection string such as:

<add name="Default" connectionString="server={ServerName};Initial Catalog=master;uid=uid;pwd=pwd" provider="System.Data.SqlClient"/>

As you can see, I’m defining the env setting once and then reusing that in the “ServerName” setting, which is then used in the connection string.

To get the “expanded” values, you simply call the Expand() extension method on string. For instance:

var connectionString = ConfigurationManager.ConnectionStrings["Default"].ConnectionString.Expand();
// returns "server=dbserver01-dev;Initial Catalog=master;uid=uid;pwd=pwd"

or you can use the dynamic ConfigurationManager wrapper “Config” as follows:

var connectionString = Config.ConnectionStrings.Default;
// returns "server=dbserver01-dev;Initial Catalog=master;uid=uid;pwd=pwd" without needing explicit call to Expand()

By default expansive looks in your web.config or app.config appSettings for the tokens to lookup and expand. However, you can change this or provide your own “source” in the form of a Func<string, string> lambda on the call to Expand() which you’ll see in one of the examples below.

While you obviously have to take care in setting this up the first time, it allows for easily making changes to a series of settings by following a composition model where settings build on one another.

This web.config / app.config example is probably the most common, but this can also be used for string formatting / templating.

2. String Formatting

How many times have you written something like:

var welcomeMessage = string.Format("Hello, {0}", "John");

While it’s a fairly simple example and pretty easy to see from the argument context that the name “John” will get substituted in place of the “{0},” often times these types of strings are in a resource file, config file or database and when looking at them alone and without argument context, it’s not always easy to see what the ‘expectations’ of that string are. For instance if this were localized, it might just read “{0}, {1}” in a resource file. While the key may be something like “welcomeMessage,” it still may not be immediately apparent what that string format requires.

How much more readable and explicit would it be if we could write:

// Simple positional based formatting
// Essentially gets transformed into string.Format("{0} {1}","Hello", "John")
var welcomeMessage = "{greeting}, {firstName}".Expand("Hello", "John");

This is is the simple alternative to string.Format() that Expansive provides in the form of an a simple Expand() extension method on string.

Remember, if I hadn’t provided the arguments (“Hello” and “John”) to the Expand() method, it would have looked for “greeting” and “firstName” keys in my web.config / app.config appSettings. Again, this is just the default, but you can change it globally or on a per call basis. For instance, you could tell Expansive to pull these values out of resource file, a database table, from a webservice, what have you.

Some other ways in which you could accomplish the same thing with Expansive would be:

// Same as above just with variables defined first
// NOTE: This is positional replacement, not actual string interpolation based on variable names
// Again, this gets tranformed into string.Format("{0}, {1}", "Hello", "John")
var greeting = "Hello";
var firstName = "John";
var welcomeMessage = "{greeting}, {firstName}".Expand(greeting, firstName);

or

// Example using a Dictionary<string, string> and containing key/value pairs for expansion
// This could come from a database, file, web service, etc.
var resourceDictionary = new Dictionary<string, string> {
 {"greeting","Hello"}
 ,{"firstName","John"}
};

// call Expand() passing in a custom Func<string, string> lamda for key/value lookup
var welcomeMessage = "{greeting}, {firstName}".Expand(key => resourceDictionary[key]);

Note, you could also do this:

// Example of reusing tokens inside of another string
// NOTE: This is positional replacement, not actual string interpolation based on variable names
// This essentially becomes string.Format("FirstName: {0}, LastName:{1}, FullName: {0} {1}", "John", "Smith")
var firstName = "John";
var lastName = "Smith";
var fullName = "{firstName} {lastName}"
var welcomeMessage = "FirstName: {firstName}, LastName: {lastName}, FullName: {fullName}".Expand(firstName, lastName, fullName);

// NOTE: For fullName to work above, the "{firstName}" "{lastName}" tokens must have been in the string to be expanded.

So, as you can see this is pretty powerful and easy to read in that you can assign friendly names to the tokens vs. just have {0}, {1}, {2}… etc.

3. Model-based Templating

Additionally, Expansive can be used for model-based templating using the Expand(object model) method.

This allows you to do the following:

var model = new { FirstName = "John", LastName = "Smith" };

var testString = "First:{FirstName}, Last:{LastName}".Expand(model);
// returns "First:John, Last:Smith";

Here, Expansive replaces the tokens in the string with the values of the corresponding properties on the passed model object. Nice and clean!

Arguably, this is the most powerful feature and my favorite to use, but I’m curious to get your take.

Download it from GitHub or install it using NuGet and let me know what you think.

Enjoy!

SimpleMembership.Mvc3 – 1.1 Published

If you’re unfamiliar with SimpleMembership.Mvc3, please see this post.

Update: May 18, 2011 – Version 1.1 published to NuGet.org

This includes:

  • Minor fix to WebSecurityService to address bug reported by Phil Haack.
  • Added assembly reference to web.config.transform to reference WebMatrix.Data. Some users have reported exceptions being thrown trying to reference that namespace.
  • New SimpleMembershipAccountController which can be used as a drop-in replacement for the default AccountController in new Mvc projects. This controller uses WebSecurityService instead of the FormsAuthenticationService and MembershipService for authentication and membership. The SimpleMembershipAccountController has been moved to a new sample package: SimpleMembership.Mvc3.Sample It can be used as a drop-in replacement for the default AccountController in the Mvc3 Visual Studio project template. It uses the WebSecurityService from SimpleMembership.Mvc3 instead of the FormsAuthenticationService and MembershipService which come in the default project template.

 

SimpleMembership.Mvc3 NuGet Package

SimpleMembership.Mvc3 – 1.0

Enables the SimpleMembership API from WebMatrix/WebPages (i.e. WebSecurity) to be used with ASP.NET MVC3. This allows you to use the WebSecurity helper found in the WebMatrix.WebData namespace.

Update: February 28, 2011 – Version 1.0 released

This includes:

  • The App_Start convention from David Ebbo’s post.
  • An updated dependency on WebActivator 1.3.2 or greater (This allows us to use the new PostApplicationStartMethod in WebActivator which allows us to remove the need to modify global.asax.cs).
  • Removed need to modify global.asax.cs
  • Now, the call to WebSecurity.InitializeDatabaseConnection() is in the new Post App Startup method called Initialize() inside App_Start/SimpleMembershipMvc3.cs. This is where you’ll need to specify your connection string and user table.

Features

  • Includes a web activator and web.config transforms that enable the SimpleMembershipProvider
  • Includes an abstraction of the WebSecurity helper (IWebSecurityService) and an implementation (WebSecurityService) to enable use with DI/IoC frameworks such as NInject, etc.

Usage

  1. Modify the Initialize() method in App_Start/SimpleMembershipMvc3.cs to point to your connection string and user table.
  2. That’s It!

Using the IWebSecurityService abstraction

This package includes an abstraction of the WebSecurity interface (Services/IWebSecurityService) as well as an implementation of this interface (Services/WebSecurityService). This is useful for scenarios like using WebSecurity with Ninject or another IoC/DI framework to avoid hard references to WebSecurity and improve testability. To use this:

  • First, make sure you register WebSecurityService as an IWebSecurityService with your IoC container.
  • Next, remove the call to WebSecurity.InitializeDatabaseConnection from the Initialize() method in App_Start/SimpleMembershipMvc3.cs
  • Finally, uncomment the following lines and modify the call to InitializeDatabaseConnection() to point to your connection string and user table:
var webSecurityService = DependencyResolver.Current.GetService<IWebSecurityService>();

webSecurityService.InitializeDatabaseConnection(connectionStringName: "Default", userTableName: "Users", userIdColumn: "ID", userNameColumn: "Username", autoCreateTables: true);

Currently, the package includes the actual WebMatrix.WebData.dll assembly. I’m looking into changing the package to instead use powershell to add the reference to the project if it already exists on the user machine.

Enjoy!

Adam