Dynamic Data Entities, Foreign Key and DynamicControl - value is null

  • Thread starter Thread starter Pete Hurst
  • Start date Start date
P

Pete Hurst

Hi,

Working on my first commercial project with Dynamic Data Entities I've run
into a fairly major problem.

My admin area is scaffolded and inserts/updates are working fine. I'm now
trying to create the actual pages of the website to display data to the
public.

Firstly, I'm not sure if I'm going about this the right way, but there are
no examples out there of how to do this. All the tutorials and documentation
surrounding Dynamic Data simply show you how to scaffold and customise your
tables. I've found so few examples of how to actually start building the
rest of the site (whilst still taking advantage of DD) and those I have seen
have been simple to the point of laughability. So, if there is an easier way
I could achieve this, or if I am not following best practise, please let me
know!

I'm trying to set up a route which looks like: ~/Customers/{name}.aspx

I then want to use value of the {name} token to filter my Customers table
and display details of that customer.

The only way I found to achieve this, was in an IRouteHandler to instantiate
the correct page and pass in the token. Then in my page class I manually add
a Parameter to the WhereParameters collection of an EntityDataSource. This
is working fine, but seems like a horrifically ugly way of acheiving
something that should be easy.

Here is where my problem occurs. My Customer object has a Logo property,
which is a (nullable) foreign key association to an Images table. I've added
a UIHint to this property to use a FieldTemplate called "Image". This works
fine when editing a Customer in my scaffolding. However when I render the
Logo field in a ListView using a DynamicControl, it doesn't work. The
FieldValue property of my FieldTemplateUserControl is null, where normally
it would contain an Image business object! (I stated the foreign key is
nullable and non-enforced, however in this case the database field is not
null and has a valid ID)

I've tried removing the UIHint to check if it was a problem with my field
template, and no - the default ForeignKey field template that is used by
Dynamic Data also fails to render.

I've tried adding a DynamicDataManager to the page, with
AutoLoadForeignKeys="true", and then used
DynamicDataManager1.RegisterControl(CustomerListView), but this still
doesn't solve the problem.

Is this a problem with DDE or am I missing something obvious?

Thanks in advance,
Pete Hurst
 
Hi Pete,
I'm trying to set up a route which looks like: ~/Customers/{name}.aspx
I then want to use value of the {name} token to filter my Customers table
and display details of that customer.

From your description I think what you want to achieve is a technique
called URL rewrite. More specifically, you can try this to do so (the
database in the sample is Northwind):

In the Global class, add following code:

const string _tablename = "Customers";
const string _extension=".aspx";
const string _rewritepathfirst="Details.aspx";
const string _fieldname="CustomerID";

void Application_BeginRequest(object sender, EventArgs e) {
string[] s= Request.Path.Split('/');
string last;
if (s.Length > 1&&s[s.Length-2]==_tablename)
{
last = s[s.Length-1];
if (last.EndsWith(_extension))
{
string customerid = last.Substring(0,
last.LastIndexOf('.'));
Context.RewritePath(string.Format(
"{0}?{1}={2}", _rewritepathfirst, _fieldname,
customerid));
}
}

}

Then if you enter something like "http://localhost/Customers/ANATR.aspx"
you'll see the page
"http://localhost/Customers/Details.aspx?CustomerID=ANATR" as what you see
if the above code is not added.

You can also read config settings to make it more configurable. Fore more
details please check out:
http://msdn.microsoft.com/en-us/library/ms972974.aspx

If it's not what you need, please clarify the problem. You can send me a
demo that can reproduce this issue and screenshots that can help to clarify
it. My email is (e-mail address removed) update here after sending the
project in case I missed that email.

Regards,
Allen Chen
Microsoft Online Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the

support we provide to you. Please feel free to let my manager know what you
think of the level of service provided.

You can send feedback directly to my manager at: (e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/en-

us/subscriptions/aa948868.aspx#notifications.

Note: MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community

or a Microsoft Support Engineer within 2 business day is acceptable. Please
note that each follow up response may

take approximately 2 business days as the support professional working with
you may need further investigation to

reach the most efficient resolution. The offering is not appropriate for
situations that require urgent, real-time

or phone-based interactions. Issues of this nature are best handled working
with a dedicated Microsoft Support

Engineer by contacting Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/en-

us/subscriptions/aa948874.aspx
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
Hi Allen,

Apologies for the confusion - I have no problem with rewriting, my main
problem is that a DynamicControl appears to be breaking when I use it to
render a foreign key field.

I wasn't aware of Context.RewritePath which does look very useful in classic
ASP.NET websites. However I am using Dynamic Data and the Routing engine
from ASP.NET 3.5 SP1, which are entirely different beasts! The Routing
engine was designed primarily to make URL rewriting much easier.

In my Global.asax.cs I have the following:

public static void RegisterRoutes(RouteCollection routes)
{
MetaModel model = new MetaModel();

// IMPORTANT: DATA MODEL REGISTRATION
// Uncomment this line to register LINQ to SQL classes or an
ADO.NET Entity Data
// model for ASP.NET Dynamic Data. Set ScaffoldAllTables = true
only if you are sure
// that you want all tables in the data model to support a
scaffold (i.e. templates)
// view. To control scaffolding for individual tables, create a
partial class for
// the table and apply the [Scaffold(true)] attribute to the
partial class.
// Note: Make sure that you change "YourDataContextType" to the
name of the data context
// class in your application.
model.RegisterContext(typeof(MyEntities), new
ContextConfiguration() { ScaffoldAllTables = true });

// The following statement supports separate-page mode, where
the List, Detail, Insert, and
// Update tasks are performed by using separate pages. To enable
this mode, uncomment the following
// route definition, and comment out the route definitions in
the combined-page mode section that follows.
// NOTE: I have changed this from the default route to place the
scaffolded
// tables under ~/Admin
routes.Add(new DynamicDataRoute("Admin/{table}/{action}.aspx")
{
Constraints = new RouteValueDictionary(new { action =
"List|Details|Edit|Insert" }),
Model = model
});

// Here is where I set up the rewrite to the Customer details
page:
routes.Add(new Route("Customers/{name}", new
CustomersRouteHandler("~/Customers/Default.aspx")));

}


Then, my CustomersRouteHandler class looks like this:

public class CustomersRouteHandler : IRouteHandler
{
public CustomersRouteHandler(string virtualPath)
{
_virtualPath = virtualPath;
}


string _virtualPath;


#region IRouteHandler Members

public System.Web.IHttpHandler GetHttpHandler(RequestContext
requestContext)
{
var display = BuildManager.CreateInstanceFromVirtualPath(
_virtualPath, typeof(Page)) as ICustomersPage;

display.CustomerName = requestContext.RouteData.Values["name"]
as string;
return display;
}

#endregion
}



My ~/Customers/Default.aspx implements ICustomersPage allowing the
CustomerName property to be set on it. Then I am manually adding a Parameter
into the WhereParameters collection of an EntitiesDataSource, early in the
lifecycle. This is working, but I'm wondering if there is a better practice
(in particular a more declarative way of acheiving this). The code (in
OnInit) is as follows:

CustomersDataSource.WhereParameters.Add(new
Parameter("CustomerName", System.Data.DbType.String, CustomerName));


*However* my main problem comes when I then render the data source using a
ListView containing DynamicControl fields. The customer record is displaying
correctly *except for* the Logo foreign key field I described, which is
giving me a null value.

My page markup looks like this:

<asp:EntityDataSource runat="server" Where="it.CustomerName=@CustomerName"
ID="CustomersDataSource" ContextTypeName="MyEntities"
EntitySetName="Customers">
</asp:EntityDataSource>
<asp:ListView runat="server" DataSourceID="CustomersDataSource"
ID="CustomerDetails">
<LayoutTemplate>
<asp:PlaceHolder runat="server"
ID="itemPlaceholder"></asp:PlaceHolder>
</LayoutTemplate>
<ItemTemplate>
<h2>
<asp:DynamicControl ID="LogoDisplay" DataField="Logo" runat="server"
/>
<asp:DynamicControl ID="NameDisplay" DataField="Name" runat="server"
/>
</h2>
</ItemTemplate>
</asp:ListView>


The LogoDisplay control should be rendering the foreign key field (and via
my UIHint should be doing so with my Image custom field template, instead of
the default ForeignKey template). Unfortunately during DataBinding, the
field template's FieldValue is null. If I remove the UIHint, then the
default ForeignKey template *also* has this issue so I know it's not a
problem with the way I've made my field template.

To be honest it would take some time to package the project for you to look
at, because I am linking several of my own libraries from different
locations on my hard drive and in addition it requires my SQL database and
various other components. I'm rather hoping that somebody out there has
enough knowledge of Dynamic Data, and using the DynamicControl with foreign
key fields, to have had experience of this and be able to tell me how to
achieve what I imagine is a standard and everyday scenario! ...or at least
point me towards examples/tutorials on building a Dynamic Data Entities
website beyond the very basic admin scaffolding paradigm.

Pete
 
Ok, I've found the solution.

I had to add Include="Logo" to my EntitiesDataSource to force that foreign
key to be loaded.

Quite why this is necessary I don't know (surely AutoLoadForeignKeys should
have done this!) and is probably something that needs to be documented
better. Ah well, it's fixed.

But if anyone has any further insight into Routing and using route tokens in
page queries, that would be wonderful.

Pete
 
Back
Top