Recently, I was trying to use ASP.NET Profile Provider for one of my application but soon ran into trouble due to compatibility issues with my CMS system and complexity involved. I decided to build a generic dynamic Profile class and a Provider to support it. Code related to dynamic profile is available on github.
I call this as dynamic profile just because it provide the untyped and runtime access to profile properties, this allows to work with structure without having static type.
There are two main components of Dynamic Profile
- Profile class
- IProfileService implementation
Profile Class
Profile class is an implementation of DynamicObject with auto detection of current context user or anonymous id, its constructor has a dependency on IProfileService implementation to get/set the data.
Profile class does following
- It has a constructor which relies on ASP.NET Anonymous module to track anonymous users or current Identity for authenticated user
- An Init method to initialize the properties of the profile from data source with help of IProfileService implementation.
- DynamicObject’s method implementation TryGetMember/TrySetMember to get/set the properties in the internal memory.
- Save method to persist the profile properties i.e. Property Name and value in the associated store with help of IProfileService Implementation.
IProfileService
IProfileService is the heart of the implementation, it works as Provider for Profile class to retrieve/store profile properties from a persistence store. Actual interface as such is very simple and straight forward with 2 generic method 1) GetPropertyValues 2) SetPropertyValues but implementation can be complex based on the data store chosen and logic required to store the nested values and their type.
/// <summary> /// IProfileService /// </summary> public interface IProfileService { /// <summary> /// GetPropertyValues /// </summary> /// <param name="userName"></param> /// <returns></returns> Dictionary<string, object> GetPropertyValues(string userName); /// <summary> /// SetPropertyValues /// </summary> /// <param name="userName"></param> /// <param name="properties"></param> void SetPropertyValues(string userName, Dictionary<string, object> properties); }
Current implementation stores the values in XML file with file name is unique to either user name or ASP.NET anonymous id, this uses different internal method to serialized/deserialize properties and values in xml along with their type name.
A sample output of current implementation looks like below
<?xml version="1.0" encoding="utf-8"?> <profile> <FirstName type="System.String">Chandra</FirstName> <LastName type="System.String">Prakash</LastName> <Name type="System.String">Hello Mr.!!! Chandra Prakash </Name> <Address type="CPrakash.Web.Profile.Mvc.Models.Address"> <Street type="System.String">Jefferson</Street> <Unit type="System.String">Line1</Unit> <City type="System.String">Louisville</City> <State type="System.String">KY</State> <ZipCode type="System.String">40220</ZipCode> </Address> </profile>
How to use it
As we are trying to store any type of property values in compile time it is required that object declared is of dynamic type.
Declaration
dynamic profile = new Profile(new ProfileService());
Retrieving the values
var firstName = profile.FirstName; var lastName = profile.LastName; var address = profile.Address;
Assigning the values (No save)
if(string.IsNullOrWhiteSpace(name)) profile.Name = string.Format("Hello Mr.!!! {0} {1}", firstName, lastName); if(address == null) address = new Address { Street = "MyStree", Unit = "Line1", City = "MyCity", State = "MyState", ZipCode = "MyZipCode" }; profile.Address = address;
Storing the values in persistence store
profile.Save();
All code and a sample app with implementation is available on github.
This is very basic implementation and requires enhancement in order to be used in production system, let me know if you have any suggestion and challenges in using this solution.