As some of you know, I enjoy working at high-throughput web applications. One thing I however don't particularily like, is the creation of the necessary backend administration tools. In a lot of the applications I've worked on, data is fed using various XML-ish or proprietary data feeds and is usually 99.9% correct. For the remaining 0.1%, support personell needs some possbility to maintain and change data in every way imaginable. This usually means that it's necessary to create CRUD-style data maintainance applications for dozens or - more likely - hundreds of tables.
As this doesn't really sound like a lot of fun, I had high hopes that ASP.NET Dynamic Data would help our clients a bit in this regard. And, yes, it does! Now, to be fair: it's Version One and lacks a few features which would be nice. But the cool thing is that it's extremely extensible.
As those of you who've looked at dynamic data before will know, ADD by default bases its view of the world on annotated partial classes based on code generated from an Entity Framework EDMX or on Linq-To-SQL classes. This of course also means that, by default, you will get exactly one representation for each class (one set of configured columns). There is no built-in (automatic) way to simply configure different views, including different columns in different orders for each table. For most of the applications my clients work with, this is unfortunately not enough, as their users usually want to show/hide different columns based on the particular use case.
What I'd like to do instead was to define multiple views (say, in an XML file) and define key for each view which can then be used to retrieve the desired layout. (Note: the following sample is based on an Entity Framework Dynamic Data Web Site based on the Northwind database ... But I'm sure that you can follow even without this setup):
The first thing was to define the different columns I'd like to show in the different contexts. To do this, I've created a file called ColumnConfiguration.config in the Web's root directory:
<ColumnConfigurations> <Configuration Table="Customers" Name="Phonelist" Columns="CompanyName, ContactName, ContactTitle, Phone, Country" /> <Configuration Table="Customers" Name="Complete" Columns="*" /> <Configuration Table="Products" Name="Shortlist" Columns="ProductName, UnitsInStock, QuantityPerUnit" /> </ColumnConfigurations>
I've then created a custom field generator (loosely based on the one which has been published last year with the ASP.NET dynamic data futures ... from which I also took the ColumnOrder-Attribute which I include for completeness' sake).
public class ConfigurationBasedFieldGenerator : IAutoFieldGenerator
{
private MetaTable _table;
private bool _multiItemMode;
private string _configurationName;
public static Dictionary> _configurations = new Dictionary>();
public static DateTime _nextRefresh = DateTime.MinValue;
private void EnsureConfigurations()
{
lock (_configurations)
{
if (_nextRefresh > newConfigs = new Dictionary>();
using (XmlReader rdr = new XmlTextReader(HttpContext.Current.Server.MapPath("~/ColumnConfiguration.config")))
{
rdr.Read();
rdr.ReadToDescendant("Configuration");
while (rdr.Name == "Configuration")
{
string name = rdr.GetAttribute("Name");
string table = rdr.GetAttribute("Table");
string columns = rdr.GetAttribute("Columns");
List tmp = new List(columns.Split(','));
for (int i = 0; i ().DefaultIfEmpty(ColumnOrderAttribute.Default).First();
}
public ICollection GenerateFields(Control control)
{
EnsureConfigurations();
bool isWildcardConfig= true;
string key = _table + "|" + _configurationName;
List columnsToInclude=null;
bool hasKey = _configurations.TryGetValue(key, out columnsToInclude);
if (hasKey)
{
if (columnsToInclude.Count==0 || columnsToInclude[0] != "*")
{
isWildcardConfig = false;
}
}
if (isWildcardConfig)
{
// use standard config, ordered by ColumnOrderAttribute - borrowed from an older version
// of the ASP.NET futures
var fields = from column in _table.Columns
where IncludeField(column)
orderby ColumnOrdering(column)
select new DynamicField()
{
DataField = column.Name,
HeaderText = column.DisplayName
};
return fields.ToList();
}
else
{
var allFields = from column in _table.Columns
where IncludeField(column)
select new DynamicField()
{
DataField = column.Name,
HeaderText = column.DisplayName
};
List fields = new List();
foreach (string col in columnsToInclude)
{
DynamicField field = allFields.FirstOrDefault(p=>p.DataField == col);
if (field != null) fields.Add(field);
}
return fields;
}
}
}
// borrowed from an older version of the asp.net futures
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = true, AllowMultiple = false)]
public class ColumnOrderAttribute : Attribute, IComparable
{
public static ColumnOrderAttribute Default = new ColumnOrderAttribute(0);
public ColumnOrderAttribute(int order)
{
Order = order;
}
///
/// The ordering of a column. Can be negative.
///
public int Order { get; private set; }
public int CompareTo(object obj)
{
return Order - ((ColumnOrderAttribute)obj).Order;
}
}
To enable this custom field generator, I've changed the default List.aspx (and the other view as well) to explicitly use it:
protected void Page_Init(object sender, EventArgs e)
{
table = GridDataSource.GetTable();
string configurationName = Request.QueryString["config"];
DynamicDataManager1.RegisterControl(GridView1, true /*setSelectionFromUrl*/);
GridView1.ColumnsGenerator =
new ConfigurationBasedFieldGenerator(table, configurationName, true);
}
Et voilà. If I browse to http://localhost/Customers/List.aspx, I get the full list (as configured in the metadata), but if I browse to http://localhost/Customers/List.aspx?config=Phonelist, I only get the fields which have been configured in ColumnConfiguration.config (CompanyName, ContactName, ContactTitle, Phone, Country .... exactly in this sequence!). I could of course also define more than one additional view just by adding the entries to the configuration file.
And to take this one step further, you could imagine to also add attributes like "RoleName" to the configuration file to automatically check the user's role membership to ensure that only users with the correct access rights can view certain combinations of columns.
The posted code is not correct, can you paste or escape correctly the code?
Posted by: Costantino | 05/18/2009 at 07:35 PM
asp.net comments using server side comments that can disabled code controls in the page. Because AJAX enabled the comment form.
Posted by: sikat ang pinoy | 02/10/2010 at 01:34 AM
Some time ago, I really needed to buy a good house for my business but I did not earn enough money and could not buy anything. Thank goodness my colleague suggested to try to take the personal loans from reliable bank. Hence, I did that and was happy with my short term loan.
Posted by: Bonner21Marina | 06/29/2010 at 06:07 PM
Multiple Form Configurations with ASP.NET Dynamic Data thanx.
Posted by: cihip | 07/18/2010 at 07:16 AM
A successful businessman is a tiger, a failure of the Wolf, the businessman is dealing with which you and them?
Posted by: air jordans | 10/06/2010 at 05:06 AM
Hello!, I am visiting your site yet again to see more of your updates. I found this really interesting and felt compelled to comment a little thank you for all your effort. Please continue the great work your doing!
Posted by: nike air max | 10/08/2010 at 05:45 AM
I have nothing to offer but blood , toil tears and sweat .
Posted by: New Balance 574 | 10/14/2010 at 05:18 AM
I wholly agree that simpler documents need to be used in smaller rounds. And unfortunately, many will be enticed to use these docs without the help of an attorney, while the investors will have attorneys on their side making sure the terms are favorable to them.and when you finish your things,pls link my name to see my website about Retro Jordan,thanks.
Posted by: Retro Jordan | 10/18/2010 at 04:52 AM
When talk about field,the first sight I think that is the own of somebody,but now I haven’t thought that,because I read your post,that new opinion there,thanks,learn the knowledge from you lots.
Posted by: jordan 7 | 11/03/2010 at 08:55 AM
the wolf has a winning game.
Posted by: Supra Skytop | 11/11/2010 at 07:47 AM
Life is a struggle, accept it.
Posted by: Air Jordans | 11/12/2010 at 02:05 AM
Everyone when in childhood has a dream, the imagination of freedom fly in the sky.
Posted by: Juicy Couture Handbags | 11/15/2010 at 08:40 AM
I was a shy teenager, glad to have anyone talk to me
Posted by: Air Jordans | 11/15/2010 at 09:53 AM
oh I hope you all have a blessed days!
Posted by: shop taobao china | 11/16/2010 at 08:39 AM
[ this is good]
Posted by: Supra Vaider | 11/22/2010 at 04:35 AM
*Cool piercing!*_*
Posted by: cheap supra shoes | 12/02/2010 at 01:29 AM
A banda já vendeu mais de 100 milhões de cópias em todo o mundo, sendo cerca de 43 milhões somente nos Estados Unidos. O seu álbum de estréia em 1987, Appetite for Destruction vendeu cerca de 40 milhões de cópias no mundo todo, 23 milhões apenas nos Estados Unidos, sendo certificado 23 vezes platina pela RIAA (Associação da Indústria de Gravação da América).
Posted by: Louis Vuitton Handbags | 12/03/2010 at 08:03 AM
You're great! Thank you very much!
Posted by: registry cleaners | 12/19/2010 at 02:50 PM
Really well-written article. I'm jealous I didn't think of the topic. But yeah, the bowl games are really for the big games... everything else is just another way to suck the blood out of these kids and samll universities. Kinda sad.
But if you ARE going to go and get tickets, you might as well find yourself the best deal. I found this really cool website when digging around for tix to my game:
Posted by: Coach Outlet Stores Online | 01/05/2011 at 09:00 AM
Um...like the style of your writing.*_*
Posted by: Taobao agent | 01/06/2011 at 03:16 AM
As this doesn't really sound like a lot of fun, I had high hopes that ASP.NET Dynamic Data would help our clients a bit in this regard. And, yes, it does! Now, to be fair: it's Version One and lacks a few features which would be nice. But the cool thing is that it's extremely extensible.
Posted by: Moncler Jackets | 01/06/2011 at 10:07 AM
who've looked at dynamic data before will know, ADD by default bases its view of the world on annotated partial classes based on code generated from an Entity Framework EDMX or on Linq-To-SQL classes. This of course also means that, by default, you will get exactly one representation for each class (one set of configured columns). There is no built-in (automatic) way to simply configure different views, including different columns in different orders for each table. For most of the applications my clients work with, this is unfortunately not enough, as their users usually want to show/hide different columns based on the particular use case.
Posted by: approved payday loan | 01/13/2011 at 10:03 PM
They lope like wolves into banks, snatch fistfuls of money and live large in the face of the Great Depression .
Posted by: air jordan shoes | 02/11/2011 at 06:45 AM
Hola,
Ha hecho un trabajo muy bueno. Hay muchas personas en busca de eso ahora van a encontrar suficientes fuentes por tus consejos.
espera para obtener más consejos acerca de que
Posted by: Generic Cialis | 03/08/2011 at 06:32 AM
Wow, Great postNice work, I would like to read your blog every day Thanks
Posted by: アンカロン | 04/18/2011 at 02:50 PM