Windows Identity Foundation 4.5 Configuration - wif

We have an application that was originally built with .NET 4.0 and WIF 3.5 (1.0?). I'm in the process of converting it to use WIF 4.5 as we've upgraded the app to .NET 4.5. I've got all the code changes made and have been fighting with the configuration settings. My current dilemma is with the <claimTypeRequired> element. According to this documentation it should be a child of <identityConfiguration>, but when I modify my config to look like this
<system.identityModel>
<identityConfiguration>
<claimTypeRequired>
...
</claimTypeRequired>
I get the following error at run-time
Parser Error Message: Unrecognized element 'claimTypeRequired'.
If I just comment out the <claimTypeRequired> block I get past that error but then I'm presented with another problem. We had modified the maximumClockSkew in the existing application via the following configuration
<securityTokenHandlerConfiguration>
<maximumClockSkew value="1" />
</securityTokenHandlerConfiguration>
The configuration documentation referenced earlier doesn't even mention the maximumClockSkew. I figured I'd try leaving it in to see what happens. What happens is
Parser Error Message: Property 'maximumClockSkew' is not a ConfigurationElement.
But when I look at the SecurityTokenHandlerConfigurationElement class using JustDecompile I can see the property:
[ConfigurationProperty("maximumClockSkew", IsRequired=false, DefaultValue="00:05:00")]
[IdentityModelTimeSpanValidator(MinValueString="00:00:00")]
[TypeConverter(typeof(TimeSpanOrInfiniteConverter))]
public TimeSpan MaximumClockSkew...
So it seems like it's expecting it to be there.
It's almost like Microsoft doesn't actually want us to use this stuff.

Here's a decompilation of the IdentityConfigurationElement from resharper. You'll notice claimtyperequired is no longer a member of this element. It appears that claimTypeRequired is not part of the schema, despite the fact that it's in Microsoft's documentation.
// Type: System.IdentityModel.Configuration.IdentityConfigurationElement
// Assembly: System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.IdentityModel.dll
using System;
using System.ComponentModel;
using System.Configuration;
using System.Runtime;
namespace System.IdentityModel.Configuration
{
/// <summary>
/// Represents an <identityConfiguration> element in a configuration file. This class cannot be inherited.
/// </summary>
public sealed class IdentityConfigurationElement : ConfigurationElement
{
/// <summary>
/// Initializes a new instance of the <see cref="T:System.IdentityModel.Configuration.IdentityConfigurationElement"/> class.
/// </summary>
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public IdentityConfigurationElement();
/// <summary>
/// Gets or sets the name of the identity configuration element.
/// </summary>
///
/// <returns>
/// The name of the identity configuration.
/// </returns>
[ConfigurationProperty("name", Options = ConfigurationPropertyOptions.IsKey)]
[StringValidator(MinLength = 0)]
public string Name { get; set; }
/// <summary>
/// Gets the <see cref="T:System.IdentityModel.Configuration.AudienceUriElementCollection"/> that is associated with this identity configuration element.
/// </summary>
///
/// <returns>
/// The collection of audience URIs that are configured for this identity configuration element.
/// </returns>
[ConfigurationProperty("audienceUris", IsRequired = false)]
public AudienceUriElementCollection AudienceUris { get; }
/// <summary>
/// Gets or sets the <see cref="T:System.IdentityModel.Configuration.IdentityModelCachesElement"/> that is associated with this identity configuration element.
/// </summary>
///
/// <returns>
/// The element that configures the token replay cache and the session security token cache for this identity configuration element.
/// </returns>
[ConfigurationProperty("caches", IsRequired = false)]
public IdentityModelCachesElement Caches { get; set; }
/// <summary>
/// Gets or sets the <see cref="T:System.IdentityModel.Configuration.X509CertificateValidationElement"/> that is associated with this identity configuration element.
/// </summary>
///
/// <returns>
/// The element that configures the certificate validator and its properties for this identity configuration element.
/// </returns>
[ConfigurationProperty("certificateValidation", IsRequired = false)]
public X509CertificateValidationElement CertificateValidation { get; set; }
/// <summary>
/// Gets or sets the claims authentication manager that is associated with this identity configuration element.
/// </summary>
///
/// <returns>
/// A custom type element that specifies the <see cref="T:System.Type"/> of the claims authentication manager. The type must derive from <see cref="T:System.Security.Claims.ClaimsAuthenticationManager"/>.
/// </returns>
[ConfigurationProperty("claimsAuthenticationManager", IsRequired = false)]
public CustomTypeElement ClaimsAuthenticationManager { get; set; }
/// <summary>
/// Gets or sets the claims authorization manager that is associated with this identity configuration element.
/// </summary>
///
/// <returns>
/// A custom type element that specifies the <see cref="T:System.Type"/> of the claims authorization manager. The type must derive from <see cref="T:System.Security.Claims.ClaimsAuthorizationManager"/>.
/// </returns>
[ConfigurationProperty("claimsAuthorizationManager", IsRequired = false)]
public CustomTypeElement ClaimsAuthorizationManager { get; set; }
/// <summary>
/// Gets or sets the <see cref="T:System.IdentityModel.Configuration.IssuerNameRegistryElement"/> that is associated with this identity configuration element.
/// </summary>
///
/// <returns>
/// The element that configures the issuer name registry for this identity configuration element.
/// </returns>
[ConfigurationProperty("issuerNameRegistry", IsRequired = false)]
public IssuerNameRegistryElement IssuerNameRegistry { get; set; }
/// <summary>
/// Gets or sets the issuer token resolver that is associated with this identity configuration element.
/// </summary>
///
/// <returns>
/// A custom type element that specifies the <see cref="T:System.Type"/> of the issuer token resolver. The type must derive from <see cref="T:System.IdentityModel.Selectors.SecurityTokenResolver"/>.
/// </returns>
[ConfigurationProperty("issuerTokenResolver", IsRequired = false)]
public CustomTypeElement IssuerTokenResolver { get; set; }
/// <summary>
/// Gets or sets the maximum clock skew that is configured for this identity configuration element.
/// </summary>
///
/// <returns>
/// The maximum clock skew.
/// </returns>
[TypeConverter(typeof (TimeSpanOrInfiniteConverter))]
[ConfigurationProperty("maximumClockSkew", DefaultValue = "00:05:00", IsRequired = false)]
[IdentityModelTimeSpanValidator(MinValueString = "00:00:00")]
public TimeSpan MaximumClockSkew { get; set; }
/// <summary>
/// Gets or sets a value that indicates whether to save the bootstrap context in claims identities and session security tokens created by the handlers configured in this identity collection.
/// </summary>
///
/// <returns>
/// true to save the <see cref="T:System.IdentityModel.Tokens.BootstrapContext"/>; otherwise, false.
/// </returns>
[ConfigurationProperty("saveBootstrapContext", DefaultValue = false, IsRequired = false)]
public bool SaveBootstrapContext { get; set; }
/// <summary>
/// Gets or sets the service token resolver that is associated with this identity configuration element.
/// </summary>
///
/// <returns>
/// A custom type element that specifies the <see cref="T:System.Type"/> of the service token resolver. The type must derive from <see cref="T:System.IdentityModel.Selectors.SecurityTokenResolver"/>.
/// </returns>
[ConfigurationProperty("serviceTokenResolver", IsRequired = false)]
public CustomTypeElement ServiceTokenResolver { get; set; }
/// <summary>
/// Gets or sets the <see cref="T:System.IdentityModel.Configuration.TokenReplayDetectionElement"/> that is associated with this identity configuration element.
/// </summary>
///
/// <returns>
/// The element that specifies whether token replay detection is enabled and specifies the maximum expiration period for tokens in the token replay cache.
/// </returns>
[ConfigurationProperty("tokenReplayDetection", IsRequired = false)]
public TokenReplayDetectionElement TokenReplayDetection { get; set; }
/// <summary>
/// Gets or sets the <see cref="T:System.IdentityModel.Configuration.SecurityTokenHandlerSetElementCollection"/> that is associated with this identity configuration element.
/// </summary>
///
/// <returns>
/// The security token handler collections configured for this identity configuration element..
/// </returns>
[ConfigurationProperty("", Options = ConfigurationPropertyOptions.IsDefaultCollection)]
public SecurityTokenHandlerSetElementCollection SecurityTokenHandlerSets { get; }
}
}

By the way, if you haven't found out already about the claimTypeRequired attribute in the XML, you can use this as a workaround:
at the top of the config file, put this:
<section name="system.identityModel.services.serialization" type="System.IdentityModel.Services.Serialization , System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
and then around the claimTypeRequired, here's an example:
<system.identityModel.services.serialization>
<claimTypeRequired>
<claimType type="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" optional="true"/>
<claimType type="http://schemas.microsoft.com/ws/2008/06/identity/claims/role" optional="true"/>
</claimTypeRequired>
</system.identityModel.services.serialization>
Kind regards,

you were almost close this is the answer for setting it in config
<securityTokenHandlerConfiguration saveBootstrapContext="true" maximumClockSkew="00:35:00" >
It works it sets it to value of 35 minutes here. hh:MM:ss

Related

Linq Join Two Repository Asp.Net MVC

I have two Repository Stock and Inventory ,Both have Get , Insert ,Update ,delete Methods
private IStockService _stockService;
private IInventoryService _inventoryService;
public StockController(IStockService StockService, IInventoryService InventoryService)
{
_stockService = StockService;
_inventoryService = InventoryService;
}
InterFace is
public interface IStockService
{
IEnumerable<Stock> GetStock();
/// <summary>
///
/// </summary>
/// <returns></returns>
IEnumerable<Stock> GetStock(Func<Stock, bool> where);
/// <summary>
///
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
Stock GetStockById(int id);
/// <summary>
///
/// </summary>
/// <param name="objStock"></param>
void InsertStock(Stock objStock);
/// <summary>
///
/// </summary>
/// <param name="objStock"></param>
void UpdateStock(Stock objStock);
/// <summary>
///
/// </summary>
/// <param name="objStock"></param>
void DeleteStock(Stock objStock);
}
I Want To Join Two Repository Using Linq Query eg: from stock in _stock JOIN etc
You should join on GetStock() method of the first repository and ... method of the second repository with their equals fields.
Var result1 = repo.getstock();
Var result2 = repo2.yourMethodName();
And join with linq on result1 and result2

Register all modules exported using MEF and autofac

Using the Autofac.Mef extension I want to register exported Modules. Is there a way?
Exporting
[Export(typeof(IModule))]
public class MyModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<SampleJob>().AsSelf();
}
}
Registering
var catalog = new DirectoryCatalog(".");
builder.RegisterComposablePartCatalog(catalog); //This would register all exported types.
builder.RegisterModule(//All IModules registerd as that type I want to register as Modules)
There is a very good writeup about one such approach in Unleashing modules – part 2. The approach is to use a delegate as a factory to create the modules instead of exporting the IModule type.
using Autofac;
/// <summary>
/// Creates an <see cref="IModule" /> that's responsible for loading
/// dependencies in the specified context.
/// </summary>
/// <param name="mode">The mode the application is running in, let's the implementor
/// of the factory load different dependenices for different modes.</param>
/// <returns>An <see cref="IModule" />.</returns>
public delegate IModule ModuleFactory(ApplicationMode mode);
/// <summary>
/// Describes different modes an application can run in.
/// </summary>
public enum ApplicationMode
{
/// <summary>
/// The application is running in a test environment.
/// </summary>
Test = 0,
/// <summary>
/// The application is running in a staging environment.
/// </summary>
Staging = 1,
/// <summary>
/// The application is running in production environment.
/// </summary>
Production = 2
}
The real magic happens in the ComposedModule.
using Autofac.Builder;
using Autofac;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.Collections.Generic;
using System;
/// <summary>
/// An <see cref="Autofac.Builder.Module" /> is composed by with the help of
/// the System.ComponentModel.Composition (MEF) framework.
/// </summary>
public class ComposedModule
: global::Autofac.Builder.Module
{
#region Fields
private ApplicationMode mode;
private ComposablePartCatalog catalog;
[Import(typeof(ModuleFactory))]
private IEnumerable<ModuleFactory> RegisteredModuleFactories;
#endregion
#region Construction
/// <summary>
/// Creates a new ComposedModule using the specified catalog to
/// import ModuleFactory-instances.
/// </summary>
/// <param name="mode">The mode the application is running in.</param>
/// <param name="catalog">The catalog used to import ModuleFactory-instances.</param>
public ComposedModule(ApplicationMode mode, ComposablePartCatalog catalog)
{
if (catalog == null) throw new ArgumentNullException("catalog");
this.mode = mode;
this.catalog = catalog;
this.ImportFactories();
}
/// <summary>
/// Creates a new ComposedModule that loads all the ModuleFactories
/// exported in assemblies that exists in the directory specified in
/// the <param name="modulesDirectoryPath" />-parameter.
/// </summary>
/// <param name="mode">The mode the application is running in.</param>
/// <param name="catalog">The catalog used to import ModuleFactory-instances.</param>
public ComposedModule(ApplicationMode mode, string modulesDirectoryPath)
: this(mode, new DirectoryCatalog(modulesDirectoryPath)) { }
#endregion
#region Methods
private void ImportFactories()
{
var batch = new CompositionBatch();
batch.AddPart(this);
var container = new CompositionContainer(this.catalog);
container.Compose(batch);
}
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
foreach (var factory in this.RegisteredModuleFactories)
{
var module = factory(this.mode);
builder.RegisterModule(module);
}
}
#endregion
}
Usage
public class MyModule : Module
{
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
builder.RegisterType<SampleJob>().AsSelf();
}
[Export(typeof(ModuleFactory))]
public static ModuleFactory Factory = x => new MyModule();
}
See the post for complete details.
Also, you might want to check out these links:
http://buksbaum.us/2009/12/06/bootstrapping-an-application-with-mef-and-autofac/
http://kalcik.net/2014/02/09/cooperation-between-the-autofac-and-the-microsoft-extensibility-framework/

Converting from a repository factory to an IOC solutions for EF?

I have an application which borrows a lot of code from the John Papa Code Camper application. In his applicatione he uses a Repository factory to provide a new repository or an existing repository if one already exists in cache. To me this seems overly complicated and I am wondering if I could use Unity to do the same thing. Here's an example of the code that I am currently using:
In the UOW he has this code to get the repos:
public IRepository<Answer> Answers { get { return GetStandardRepo<Answer>(); } }
This code to call the repository provider:
protected IRepositoryProvider RepositoryProvider { get; set; }
protected IRepository<T> GetStandardRepo<T>() where T : class
{
return RepositoryProvider.GetRepositoryForEntityType<T>();
}
protected T GetRepo<T>() where T : class
{
return RepositoryProvider.GetRepository<T>();
}
The following respository provider:
public class RepositoryProvider : IRepositoryProvider
{
public RepositoryProvider(RepositoryFactories repositoryFactories)
{
_repositoryFactories = repositoryFactories;
Repositories = new Dictionary<Type, object>();
}
//public RepositoryProvider(RepositoryFactories repositoryFactories)
//{
// _repositoryFactories = repositoryFactories;
// Repositories = new Dictionary<Type, object>();
//}
/// <summary>
/// Get and set the <see cref="DbContext"/> with which to initialize a repository
/// if one must be created.
/// </summary>
public DbContext DbContext { get; set; }
/// <summary>
/// Get or create-and-cache the default <see cref="IRepository{T}"/> for an entity of type T.
/// </summary>
/// <typeparam name="T">
/// Root entity type of the <see cref="IRepository{T}"/>.
/// </typeparam>
/// <remarks>
/// If can't find repository in cache, use a factory to create one.
/// </remarks>
public IRepository<T> GetRepositoryForEntityType<T>() where T : class
{
return GetRepository<IRepository<T>>(
_repositoryFactories.GetRepositoryFactoryForEntityType<T>());
}
/// <summary>
/// Get or create-and-cache a repository of type T.
/// </summary>
/// <typeparam name="T">
/// Type of the repository, typically a custom repository interface.
/// </typeparam>
/// <param name="factory">
/// An optional repository creation function that takes a DbContext argument
/// and returns a repository of T. Used if the repository must be created and
/// caller wants to specify the specific factory to use rather than one
/// of the injected <see cref="RepositoryFactories"/>.
/// </param>
/// <remarks>
/// Looks for the requested repository in its cache, returning if found.
/// If not found, tries to make one using <see cref="MakeRepository{T}"/>.
/// </remarks>
public virtual T GetRepository<T>(Func<DbContext, object> factory = null) where T : class
{
// Look for T dictionary cache under typeof(T).
object repoObj;
Repositories.TryGetValue(typeof(T), out repoObj);
if (repoObj != null)
{
return (T)repoObj;
}
// Not found or null; make one, add to dictionary cache, and return it.
return MakeRepository<T>(factory, DbContext);
}
/// <summary>
/// Get the dictionary of repository objects, keyed by repository type.
/// </summary>
/// <remarks>
/// Caller must know how to cast the repository object to a useful type.
/// <p>This is an extension point. You can register fully made repositories here
/// and they will be used instead of the ones this provider would otherwise create.</p>
/// </remarks>
protected Dictionary<Type, object> Repositories { get; private set; }
/// <summary>Make a repository of type T.</summary>
/// <typeparam name="T">Type of repository to make.</typeparam>
/// <param name="dbContext">
/// The <see cref="DbContext"/> with which to initialize the repository.
/// </param>
/// <param name="factory">
/// Factory with <see cref="DbContext"/> argument. Used to make the repository.
/// If null, gets factory from <see cref="_repositoryFactories"/>.
/// </param>
/// <returns></returns>
protected virtual T MakeRepository<T>(Func<DbContext, object> factory, DbContext dbContext)
{
var f = factory ?? _repositoryFactories.GetRepositoryFactory<T>();
if (f == null)
{
throw new NotImplementedException("No factory for repository type, " + typeof(T).FullName);
}
var repo = (T)f(dbContext);
Repositories[typeof(T)] = repo;
return repo;
}
/// <summary>
/// Set the repository for type T that this provider should return.
/// </summary>
/// <remarks>
/// Plug in a custom repository if you don't want this provider to create one.
/// Useful in testing and when developing without a backend
/// implementation of the object returned by a repository of type T.
/// </remarks>
public void SetRepository<T>(T repository)
{
Repositories[typeof(T)] = repository;
}
/// <summary>
/// The <see cref="RepositoryFactories"/> with which to create a new repository.
/// </summary>
/// <remarks>
/// Should be initialized by constructor injection
/// </remarks>
private RepositoryFactories _repositoryFactories;
}
Is this something that I could use Unity for and if so can someone give me some hints on how I could create the repositories in Unity so that that they could be shared. Note that I have two types of repositories. A generic and a custom. Right now these are returned using GetStandardRepo and GetRepo. I would like if possible to have the mapping that decideds which repo I get inside my Unity config file so that it's clearly visible.
Here is the Unity Config I have so far:
container.RegisterType<RepositoryFactories>(new ContainerControlledLifetimeManager());
container.RegisterType<IRepositoryProvider, RepositoryProvider>();
container.RegisterType<IUow, Uow>();
container.RegisterType<Contracts.Services.IContentService, Services.ContentService>();
container.RegisterType<IAnswerService, AnswerService>();
Unity supports registering components "Per Request" in MVC projects. The first time a particular repository is served from the container it will be instantiated. Any subsequent requests for that repository during the same HTTP request will use this same repository rather than creating a new one.
You can read more about how this works using the link below. Basically, you're looking to control the lifetime scope of your objects as a singleton rather than for each dependency.
Unity Documentation on MSDN

Best practices for cache and session manager for an MVC Application

Masters,
We have implemented CacheManager and SessionManager in past applications by various ways, like by creating a SessionHelper static class and a CacheHelper static class.
Though it works fine, we lack some ability for generalization and globalization perspective.
So for new scratch development, we intend best practices for such general implementation in terms of flexibility and extensibility.
Please suggest.
You could create an interface to define the common operations used in Caching and Session management, named something like IStateManager. e.g.
/// <summary>
/// An interface to provide access to a state storage implementation
/// </summary>
public interface IStateManager
{
/// <summary>
/// Gets or sets the value associated with the specified key.
/// </summary>
/// <typeparam name="T">Type</typeparam>
/// <param name="key">The key of the value to get.</param>
/// <returns>The value associated with the specified key.</returns>
T Get<T>(string key);
/// <summary>
/// Adds the specified key and object to the state manager.
/// </summary>
/// <param name="key">key</param>
/// <param name="data">Data</param>
void Set(string key, object data);
/// <summary>
/// Adds the specified key and object to the state manager.
/// </summary>
/// <param name="key">key</param>
/// <param name="data">Data</param>
/// <param name="cacheTime">Cache time</param>
void Set(string key, object data, int cacheTime);
/// <summary>
/// Gets a value indicating whether the value associated with the specified key is in the state manager.
/// </summary>
/// <param name="key">key</param>
/// <returns>Result</returns>
bool IsSet(string key);
/// <summary>
/// Removes the value with the specified key from the state manager.
/// </summary>
/// <param name="key">/key</param>
void Remove(string key);
/// <summary>
/// Removes items by pattern
/// </summary>
/// <param name="pattern">pattern</param>
void RemoveByPattern(string pattern);
/// <summary>
/// Clear all state manager data
/// </summary>
void Clear();
}
Then, you could create implementations of the interface to provide different functionality. E.g. an in memory implementation, that uses System.Runtime.Caching
/// <summary>
/// Represents an in memory cache
/// </summary>
public class MemoryCacheManager : IStateManager
{
public MemoryCacheManager()
{
}
protected ObjectCache Cache
{
get
{
return MemoryCache.Default;
}
}
/// <summary>
/// Gets or sets the value associated with the specified key.
/// </summary>
/// <typeparam name="T">Type</typeparam>
/// <param name="key">The key of the value to get.</param>
/// <returns>The value associated with the specified key.</returns>
public T Get<T>(string key)
{
return (T)Cache[key];
}
/// <summary>
/// Adds the specified key and object to the cache with a default cache time of 30 minutes.
/// </summary>
/// <param name="key">key</param>
/// <param name="data">Data</param>
public void Set(string key, object data)
{
Set(key, data, 30);
}
/// <summary>
/// Adds the specified key and object to the cache.
/// </summary>
/// <param name="key">key</param>
/// <param name="data">Data</param>
/// <param name="cacheTime">Cache time</param>
public void Set(string key, object data, int cacheTime)
{
if (data == null)
return;
var policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime);
Cache.Add(new CacheItem(key, data), policy);
}
/// <summary>
/// Gets a value indicating whether the value associated with the specified key is cached
/// </summary>
/// <param name="key">key</param>
/// <returns>Result</returns>
public bool IsSet(string key)
{
return (Cache.Contains(key));
}
/// <summary>
/// Removes the value with the specified key from the cache
/// </summary>
/// <param name="key">/key</param>
public void Remove(string key)
{
Cache.Remove(key);
}
/// <summary>
/// Removes items by pattern
/// </summary>
/// <param name="pattern">pattern</param>
public void RemoveByPattern(string pattern)
{
var regex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
var keysToRemove = new List<String>();
foreach (var item in Cache)
if (regex.IsMatch(item.Key))
keysToRemove.Add(item.Key);
foreach (string key in keysToRemove)
{
Remove(key);
}
}
/// <summary>
/// Clear all cache data
/// </summary>
public void Clear()
{
foreach (var item in Cache)
Remove(item.Key);
}
}
You could create multiple implementations of this interface, such as a 'Memcached' implementation to provide distributed caching for your application or a 'Session' implementation to provide user session based functionality.
Then, you can use your dependency container of choice to inject the implementations into your services\controllers and wire up your application.
Try and avoid static classes which can be problematic to unit test.
Can use the filter attributes for caching and can handle session through the singleton class..
http://weblogs.asp.net/scottgu/archive/2007/11/13/asp-net-mvc-framework-part-1.aspx
you can get some samples in the above link for the best way or approach to be followed.

ASP.NET MVC: creating controls dynamically

This is the control builder class...
public class ControlBuilder
{
/// <summary>
/// Html Control class for controlbuilder Control .
/// </summary>
protected HTMLControl formControl;
/// <summary>
/// Html Control class for the label.
/// </summary>
private HTMLControl labelControl;
/// <summary>
/// Getting the property for the Control .
/// </summary>
/// <history>
/// [LuckyR] 10/8/2009 Created
/// </history>
public HTMLControl Form
{
get { return formControl; }
}
/// <summary>
/// Creating a label for the Control.
/// </summary>
/// <history>
/// [LuckyR] 10/8/2009 Created
/// </history>
public HTMLControl Label
{
get { return labelControl; }
}
/// <summary>
/// Creating a construtor for the controlbuilder taking in Zero
/// arguments it creates a labl for the Control .
/// </summary>
/// <history>
/// [LuckyR] 13/8/2009 Created
/// </history>
public ControlBuilder() { }
/// <summary>
/// A construtor for the controlbuilder which
/// creates a label for the Control .
/// </summary>
/// <history>
/// [LuckyR] 10/8/2009 Created
/// </history>
public ControlBuilder(string labelName)
{
Label label = new Label();
label.Text = labelName;
label.Width= 200;
labelControl = new HTMLControl(label);
}
/// <summary>
/// Control build property that is used to biuld the Html
/// markup for the created Control.
/// </summary>
/// <history>
/// [LuckyR] 10/8/2009 Created
/// </history>
public string BuildControl()
{
this.CreateControl();
this.SetAttribute();
return this.RenderHTML();
}
/// <summary>
/// Render Html tags for the Control with label .
/// </summary>
/// <history>
/// [LuckyR] 10/8/2009 Created
/// </history>
public string RenderHTML()
{
return labelControl.RenderHTML() + ": " + formControl.RenderHTML();
}
/// <summary>
/// Used to Set Attributes for the Control .
/// </summary>
/// <history>
/// [LuckyR] 13/8/2009 Created
/// </history>
protected virtual void SetAttribute() { }
/// <summary>
/// Used to create the Control .
/// </summary>
/// <history>
/// [LuckyR] 13/8/2009 Created
/// </history>
protected virtual void CreateControl() { }
/// <summary>
/// A list of all the Controls that will be created during the
/// program run .
/// </summary>
private IList<ControlBuilder> Controls = new List<ControlBuilder>();
/// <summary>
/// A property to add Control to the ControlBuilder that are created by
/// the user.
/// </summary>
/// <history>
/// [LuckyR] 13/8/2009 Created
/// </history>
/// <param name="Control">Controls from the controlbuilder class</param>
public void AddControl(ControlBuilder Control)
{
Controls.Add(Control);
}
/// <summary>
/// A property to display the Controls that are created by
/// the user.
/// </summary>
/// <history>
/// [LuckyR] 13/8/2009 Created
/// </history>
public string Display()
{
string Html = string.Empty;
foreach (ControlBuilder builder in Controls)
{
Html += builder.BuildControl();
Html += "<br /><br />";
}
return Html;
}
}
}
this is how i build a control
public class TextBoxBuilder : ControlBuilder
{
/// <summary>
/// Creating a web Control textBox.
/// </summary>
private TextBox textBox;
/// <summary>
/// Creating an Id to add as an attribute .
/// </summary>
private string Id;
/// <summary>
/// Creating an Value to add as an attribute .
/// </summary>
private string Value;
/// <summary>
/// Creating a Textbox constructor which takes in LabelName and Id.
/// to create a label for the Control.
/// </summary>
/// <history>
/// [LuckyR] 10/8/2009 Created
/// </history>
public TextBoxBuilder(string labelName, string id , string value): base(labelName)
{
this.Id = id;
this.textBox = new TextBox();
this.Value = value;
}
/// <summary>
/// Used to Set properties for the Control .
/// </summary>
/// <history>
/// [LuckyR] 10/8/2009 Created
/// </history>
protected override void SetAttribute()
{
this.textBox.ID = this.Id;
this.textBox.Text = this.Value;
}
/// <summary>
/// Used to create the Control . That is done by calling the HtmlControl class
/// which inturn renders the particular Control for us .
/// </summary>
/// <history>
/// [LuckyR] 10/8/2009 Created
/// </history>
protected override void CreateControl()
{
this.formControl = new HTMLControl(this.textBox);
}
}
}
In my home controller i did this ...
public ActionResult Create()
{
///Where i am contacting the linq to sql classs for performing ths operagtion
foreach (var control in Rep.GetData(ScreenName))
{
string Type = control.Type;
string value = null;
if (id != Guid.Empty)
{
value = DataObj.GetValue(control.TableName, control.ControlName, id);
}
switch (Type)
{
case ("TextBox"):
/// Buliding a textBox box
controlbuilder.AddControl(new TextBoxBuilder(control.Field, control.ControlName, value));
break;
case ("CheckBox"):
/// Bulidig a CheckBox .
controlbuilder.AddControl(new CheckBoxBuilder(control.Field, control.ControlName , value));
break;
case ("DatePicker"):
/// Bulidig a DatePicker .
controlbuilder.AddControl(new DatePicker(control.Field, control.ControlName, value));
break;
case ("DropDownList"):
///Building a dropdownlist.
List<string> list = DataObj.GetDropDownValues(control.Id);
controlbuilder.AddControl(new DropDownListBuilder(control.Field, control.ControlName, list,value));
break;
case ("TextArea"):
/// Building a textBox area .
controlbuilder.AddControl(new TextArea(control.Field, control.ControlName , value));
break;
default:
break;
}
}
return View(controlbuilder);
}
The view page looks like this ...
<% using (Html.BeginForm())
{%>
<fieldset>
<legend>Fields</legend>
<p>
<%= ViewData.Model.Display() %>
</p>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
<div>
<%=Html.ActionLink("Back to List", "Index")%>
</div>
since i am passing my class into the view i can retrieve all the data there with .display .
There is no concept of controls in ASP.NET MVC any longer.
You have two options:
When the user clicks a button, you handle this POST request in a controller action, set some sort of flag in your view model to now show a textbox, then return the same view which in its turn will look at the flag and generate a text box if required. This will incur a complete round-trip which will be somewhat similar to the postback in WebForms.
You do it in-place with JavaScript. You intercept a click event on a button and you inject an input/textarea HTML element into your document structure.

Resources