More T4 Tweaks – Part 4

 

In my previous articles I have introduced T4 Templates for newcomers especially for those working in the domain of Entity Framework. In Part 3 I went through a few steps tweaking the default Template in order to force generating appropriately annotated POCO classes. I have demonstrated the results using an ASP.NET MVC2 Application accessing & validating Data via that annotated POCO class.

It turns out however, that sometimes more tweaks could be needed, especially while trying to add a WCF Data Service Layer, which would offer a RESTful Style OData Endpoint next to the Web-Application. This is a very nice and powerful extension to any Web-Application willing to offer Data-Services beyond the officially deployed application’s Web-Site. Theoretically it would be enough to right mouse button click on the MVC Application Project and add a New Item…, taking WCF Data Services from the list of available Items (Picture 1).

Picture 1

Let’s name the service WcfDataEmployeeSvc.svc whereas I’m referring to the Project downloadable at Part 3. We could configure thereafter the Service like Code 1 depicts. The only Problem with this solution is, that it will not Work while trying to access the offered Entity-Sets. Let say you would try to access the Service via this link: http://localhost:34287/WcfDataEmployeeSvc.svc/Users which immediately will result in an Exception stating:

The XML page cannot be displayed.

Cannot view XML input using XSL style sheet. Please correct the error and then click the Refresh button, or try again later.

Error Message 1

public class WcfDataEmployeeSvc : DataService<UserEmployeeDBEntities>
{
        // This method is called only once to initialize service-wide policies.
        public static void InitializeService(DataServiceConfiguration config)
        {
            config.SetEntitySetAccessRule("Users", EntitySetRights.All);
            config.SetEntitySetAccessRule("MembershipStates", EntitySetRights.AllRead);
            config.SetEntitySetAccessRule("Orders", EntitySetRights.All);
           
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        }
}
Code 1
It turns out, that the cause of this error lays in the nature of our POCO classes using dynamic proxies. WCF Data Services are unable to track changes dynamically thus the properties’ virtual modifier is the core-cause of the issue. There are two solutions or workarounds to remedy. The easy way is to just override the CreateDataSource method within the WcfDataEmployeeSvc Service class (Code 2) and disable the proxy creation:
 
        protected override UserEmployeeDBEntities CreateDataSource()
        {
            var dataSource = new UserEmployeeDBEntities();
            // Note prox creation is going to be disabled
            dataSource.ContextOptions.ProxyCreationEnabled = false;
            return dataSource;
        }
Code 2
This above resolution will work like a charm.
 
Let me now additionally show you one more workaround to this problem. Let’s ignore for a while the remedy presented (Code 2). We learned, that disabling dynamic proxies will resolve the issue. Dynamic proxies are represented via the entities’ virtual access modifiers. So therefore it is assumed, discarding all virtual modifiers will lead to the same remediation effect. This could be easily done tweaking once more the tt-Template.
 
Please open up the ModelTweaked.tt from previous solution and locate the lines intended to insert that virtual modifier. Picture 2 will help you in locating the call to the PropertyVirtualModifier T4 Class Section (see line 62). In Picture 3 it is depicted what exactly that T4 Class Section is doing (lines 7772 – 775), which is astonishingly simple. It will only concatenate two strings whereas the virtual keyword will be added to each publicly decorated property.
 
Picture 2
Picture 3
Similarly simple will be the resolution as well. It is therefore enough to leave intact the accessibility (private, protected or public) modifiers whereas discard the virtual. Consequently we have to delete the call to the PropertyVirtualModifier T4 Class Section. In the current Template it is called once each for Primitive Properties and Complex Properties and twice at Navigation Properties. So the Template (Picture 2) could be altered like this (Picture 4 – note line 62):
 
Picture 4
The WCF Data Service will now work fine as the generated POCO classes are missing all dynamic proxies. This however has an important and negative drawback on the ASP.NET MVC Solution. While the WCF Data Service is fine, the MVC Application will be broken while trying to access POCO’s navigation properties. Discarding all dynamic proxies we have unfortunately discarded lazy loading as well. The resolution is to use everywhere eager loading e.g. via the .Include() extension method (Code 3):
 
        public ActionResult Index(int? page)
        {
            EmployeesViewData viewData = new EmployeesViewData();
            int currentPage = page ?? 0;
         
            viewData.PreviousPage = (currentPage <= 0) ? 0 : currentPage – 1;
            viewData.NextPage = currentPage + 1;
            viewData.Employees = Context.Users
                .OfType<Employee>()
                .Include("MembershipState")
                .OrderBy(x => x.Id)
                .Skip(currentPage * perPage)
                .Take(perPage).ToList();
            if (viewData.Employees.Count() < perPage)
                viewData.NextPage = currentPage;
            return View(viewData);
        }

Conclusion: In this article we have seen how to discard the virtual modifier at code generation time which will discard dynamic proxy behavior (real time change tracking) for the generated POCO classes.

Download Code here:

http://cid-8d365142bc4869ab.office.live.com/self.aspx/.Documents/Lab12^_POCO^_MVC^_DataSvc2.zip 

 

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s