Skip to content

Entity Framework (EF) T4 template modification to output PascalCasing database objects

Greetings,

So using Entity Framework (version 5 or under at least), Database First generates a model that exactly mimics the naming convention of the database objects.

So for instance, say we have the following table named :

PERSON_DETAILS

  • FIRST_NAME
  • LAST_NAME
  • PHONE_NUMBER

 

If we were to run EF out-of-the-box Database First, the following model will be generated:

namespace ConsoleApp1
{
using System;
using System.Collections.Generic;

public partial class PERSON_DETAILS
{
public string FIRST_NAME{ get; set; }
public string LAST_NAME { get; set; }
public string PHONE_NUMBER { get; set; }

}

}

 

This is fine but a bit messy!  Some database standard naming conventions enforce the all CAPITAL letters and underscores to denote multiple words.  However in code, the PascalCasing is a more popular/readable standard.  

I will post the instructions on how to modify the out of the box T4 template to do this.

  • Double click on the Model1.tt T4.
  • Scroll down to the class “CodeStringGenerator” and add the folllowing methods:

public string PascalCase(StructuralType type)
{
if (type == null)
{
return null;
}

return PascalCase(type.Name);
}

public string PascalCase(EdmMember member)
{
if (member == null)
{
return null;
}

return PascalCase(member.Name);
}

private string PascalCase(string name)
{
name = name.ToLowerInvariant();

string result = name;
bool upperCase = false;

result = string.Empty;
for (int i = 0; i < name.Length; i++)
{
if (name[i] == ‘ ‘ || name[i] == ‘_’)
{
upperCase = true;
}
else
{
if (i == 0 || upperCase)
{
result += name[i].ToString().ToUpperInvariant();
upperCase = false;
}
else
{
result += name[i];
}
}
}

return result;
}

 

  • Under the same class, find this signature method “string Property(EdmProperty edmProperty)” and modify it as such:

return string.Format(
CultureInfo.InvariantCulture,
“{0} {1} {2} {{ {3}get; {4}set; }}”,
Accessibility.ForProperty(edmProperty),
_typeMapper.GetTypeName(edmProperty.TypeUsage),
_code.Escape(PascalCase(edmProperty)),
_code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
_code.SpaceAfter(Accessibility.ForSetter(edmProperty)));

  • Under the same class, find this signature method “string EntityClassOpening(EntityType entity)” and modify it as such:

return string.Format(
CultureInfo.InvariantCulture,
“{0} {1}partial class {2}{3}”,
Accessibility.ForType(entity),
_code.SpaceAfter(_code.AbstractOption(entity)),
_code.Escape(PascalCase(entity)),
_code.StringBefore(” : “, _typeMapper.GetTypeName(entity.BaseType)));

 

Now save the *.tt file and immediately the model classes will be updated.  

The updated model corresponding to the same table above will now look like this:

namespace ConsoleApp1
{
using System;
using System.Collections.Generic;

public partial class PersonDetails
{
public string FirstName{ get; set; }
public string LastName{ get; set; }
public string PhoneNumber{ get; set; }

}

}

The documentation on how to update the base T4 templates is not very prolific, so I hope that these step-by-step instructions help some people.  I borrowed the pascal casing method code from this site:

http://stackoverflow.com/questions/2944974/t4-fieldname-in-camelcase-without-underscore

 

Webservice call responds with a 404 Error

I have a bunch of ASMX webservices deployed to an IIS6 server.  I deployed these webservices to an IIS7.5 server and when I call one of them posting content greater than 30 megabytes, I kept receiving the following HTTP Response:

HTTP/1.1 404 Not Found
Content-Type: text/html
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Thu, 13 Sep 2012 17:28:07 GMT
Content-Length: 1245

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”&gt;
<html xmlns=”http://www.w3.org/1999/xhtml”&gt;
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=iso-8859-1″/>
<title>404 – File or directory not found.</title>
<style type=”text/css”>
<!–
body{margin:0;font-size:.7em;font-family:Verdana, Arial, Helvetica, sans-serif;background:#EEEEEE;}
fieldset{padding:0 15px 10px 15px;}
h1{font-size:2.4em;margin:0;color:#FFF;}
h2{font-size:1.7em;margin:0;color:#CC0000;}
h3{font-size:1.2em;margin:10px 0 0 0;color:#000000;}
#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:”trebuchet MS”, Verdana, sans-serif;color:#FFF;
background-color:#555555;}
#content{margin:0 0 0 2%;position:relative;}
.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;position:relative;}
–>
</style>
</head>
<body>
<div id=”header”><h1>Server Error</h1></div>
<div id=”content”>
<div class=”content-container”><fieldset>
<h2>404 – File or directory not found.</h2>
<h3>The resource you are looking for might have been removed, had its name changed, or is temporarily unavailable.</h3>
</fieldset></div>
</div>
</body>

The WS call works perfect when posting content less than 30 Megabytes.  After doing some research, I discovered that in IIS7, by default it restricts the maximum content length to 30 Megabytes.  In order to resolve this, I had to modify the web.config in my webservice and add the following :

<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength=”500000000″ />
</requestFiltering>
</security>
</system.webServer>

Note:  The maxAllowedContentLength is in bytes, so in the case above it sets the limit to 500 Megabytes.

See this link for more information about this property:

http://msdn.microsoft.com/en-us/library/ms689462%28VS.90%29.aspx

 

Forwarding external port 80?

So on my home network, I ran into an issue today….

I have a website which I want to expose to the outside/externally through the default port (e.g. 80).  I go into my router and I enable port forwarding for the web server hosting the site:

Then I open up a browser (from an external network to ensure the test), and the browser hangs and then comes back with the following error after some time:

Network Error (tcp_error)
A communication error occurred: “”
The Web Server may be down, too busy, or experiencing other problems preventing it from responding to requests. You may wish to try again at a later time.

After scratching my head and trying different options (disabling the firewall, restarting router, etc.), this error persisted.  I am able to port forward other ports just fine such as RDP, FTP, but port 80 is not working for some odd reason.  I then combed through some forums and discovered that some ISPs apparently block the forwarding of port 80!  Why?  I have no idea, feel free to comment.

Anyway, so I resolved this by simply assigning a different external port which still resolves to the internal port 80:

This did the trick.  Frustrating, but it works…

Outlook attachments can not be trusted?

So I ran into an issue today..

I developed a VSTO 2010 Word document-level customization.  I discovered when a document that has been created with this customization is sent via email and opened within Outlook, you will undoubtedly receive the following nice message:

Microsoft.VisualStudio.Tools.Applications.Runtime.CannotCreateCustomizationDomainException: This document contains custom code that cannot be loaded because the location is not in your trusted locations list: Test2 (3).doc. If you trust this document you can save and open it from a location on your computer.  For more information, see http://go.microsoft.com/fwlink/?LinkId=99104.

Image

So this customization is being developed for a small internal organization which frequently will be emailing such documents back and forth to each other.  Working around this error message every time they attempt to open a customized document will become more than just a nuisance!  So the first instinct is to attempt to simply trust this location where this document is being opened from.  By default, when opening an Outlook attachment directly, it will copy it to the “Temporary Internet Files” special folder for that user.  So in the case of the document above, I found this location to be:

C:\Users\khalidk\AppData\Local\Microsoft\Windows\Temporary Internet Files\Content.Outlook\R4L3TC12\Test3.doc

So perhaps a first instinct of some people would be to try to trust this location.  Opening Microsoft Word, and going to “Options”->”Trust Center”->”Trust Center Settings”->”Trust Locations”->”Add new location..”

And then providing this path:  “C:\Users\khalidk\AppData\Local\Microsoft\Windows\Temporary Internet Files”  with the “Subfolders of this location are also trusted” option checked, will result in the following error dialogue box:

Image

So, Microsoft has decided that Outlook attachments can never be trusted; This article talks about how Outlook attachments default to being opened under “Protected View” mode :

http://office.microsoft.com/en-us/word-help/what-is-protected-view-HA010355931.aspx

Enable Protected View for files that are located in potentially unsafe locations    This refers to folders on your computer, or network, which are considered unsafe, such as the Temporary Internet folder.

However even enabling protected view for Outlook attachments will not trust the location – the 2 are different concepts.

In my next blog post, I will post a work around solution for how to get around this annoyance.  It’s worth noting first off the sequence of events that take place when initializating the “trust” status of a document:

http://msdn.microsoft.com/en-us/library/bb157863.aspx#GrantingTrustToSolutions

VSTO security - installing from Microsoft Office

Note that the very first check is to confirm whether the document is in a “trusted location” folder.  So even signing the document/customization with a certificate would not get around this.  A question I have is why doesn’t the workflow first check to see if it’s signed before checking the “trusted location” folder?  Anyway, in the next blog posting, I will walk through an add-in I developed to allow the users to open these customized documents flawlessly as if they were trusted.