Add MVC capabilites to ASP.NET webform application

Because they both are built on the same framework, it’s pretty simple to get the two to play nice together. I used this as a guide: http://guy.dotnet-expertise.com/PermaLink,guid,4f5a8ea1-1f90-4b32-a635-1d73d906aeca.aspx. It’s an old article but it worked for me. I’m using Visual Studio 2010, .NET 4.0 and MVC 3 with Razor.

The steps are as follows:

Add the following 3 references to your project:
System.Web.Abstraction
System.Web.Mvc (be aware of what DLL version you’re adding)
System.Web.Routing

Modify the project’s web.config. The easiest way is to create a new MVC project and copy over the value from there. You need to copy over the following sections, but don’t overwrite the existing values:
Compilation
Pages
HttpHandlers (this didn’t apply for me because it wasn’t in the MVC web.config. Might be a .NET 4.0 or MVC 3 thing.)
System.WebServer
Runtime

Next modify Global.asax Application_Start method to perform the same functions as your temp MVC functions.

Then copy the web.config in the View folder of the MVC project and paste it in the View folder of your webform project. Also don’t forget to copy any scaffolding files such as _Layout.cshtml and _ViewStart.cshtml.

Finally, you need to let Visual Studio know that your project now handles MVC pages as well. This will allow you to use the IDE to create Controller, Views, and other MVC goodies. Open the temp MVC project file in notepad and look for the <ProjectTypeGuids> section. Copy that guid and add it to your webform project folder. The guid in my project is {E53F8FEA-EAE0-44A6-8774-FFD645390401}.

That’s it. Now you should be able to create MVC files just was if the webform project was an MVC project itself.

An easy way to create a self signed certificate

I needed to create a self signed cert to test my WCF service with username authentication in my dev environment (if you need help with this, I recommend http://www.devatwork.nl/2007/05/wcf-username-authentication/). Tried using Windows makecert cmd utility but it was give me problems. So I found a nifty tool from pluralsite called self-cert (http://www.pluralsight-training.net/community/blogs/keith/archive/2009/01/22/create-self-signed-x-509-certificates-in-a-flash-with-self-cert.aspx). It has a simple intuitive UI and works like a charm. But don’t forget to run it as an administrator.

WCF basicHttpBinding – 504 Gateway Timeout

I had a WCF service secured with SSL, using wsHttpBinding, Message security mode, and UserName authentication. Everything worked find because I created the client app in VisualStudio and it automatically generated the appropriate tags in web.config. I was able to connection, authenticate and call methods without issue.

But now I need to adjust the service to allow clients of other technologies to connect to it…more specifically PHP. PHP can’t connect to a service that uses wsHttpBinding. It has to be basicHttpBinding because it conforms to a broader standard.

The first thing to do is change system.serviceModel/services/service binding attribute to “basicHttpBinding”. Then create a <basicHttpBinding> node under system.serviceModel/bindings. Because we can’t use the Message security mode with basicHttpBinding, it needs to be changed to TransportWithMessageCredential. And that’s basically it for the service.

Now just publish it, connect to it from your client and call it a day. Well it didn’t go that smoothly for me. My client app I create for the original wsHttpBinding service was griping with an error: The remote server returned an error: (504) Gateway Timeout. Update the service reference? Nope that didn’t help. Remove and create the service reference? Nope, same error. So then I tried playing with the service configuration to no avail.

Finally I decided to read the stack trace and saw “There was no endpoint listening at https://myremoteservername/service.svc that could accept the message. This is often caused by an incorrect address or SOAP action.” Weird, how did it know the name of my server? I went back to my client’s web.config and looked at the endpoint VS created with I added the service reference. Indeed the address contained the server name! I changed it to the publicly accessible domain name and it works.

For some reason, when VS references a service with basicHttpBinding, it uses the server name. But I have no idea how it got the name in the first place. When adding the reference, I entered the public (correct) .svc url.

I’ll have to check with our network guy about it but I’m happy it’s finally working.

iTextSharp – Removing Fields from PDF templates

Sometimes the iTextSharp RemoveField() method won’t work. This is likely because the PDF template was created in Adobe LiveCycle. LiveCycle saves the file in XFA format. iTextSharp functionality against XfA files are limited to get and set. RemoveField(), at least for now, only works on AcroForm templates created in Adobe Acrobat.

BTW, here’s the code to read from a template, edit a field and save to a new file…or output to the browser.

string templateFile = Server.MapPath(“pdf/FSSTemplate.pdf”);
string newFile = Server.MapPath(“pdf/FSS.pdf”);

PdfReader reader = new PdfReader(templateFile);
PdfStamper stamper = new PdfStamper(reader, new FileStream(newFile, FileMode.Create));

//Use the two lines below to write the pdf to the browser
//MemoryStream ms = new System.IO.MemoryStream();
//PdfStamper stamper = new PdfStamper(reader, ms);

AcroFields fields = stamper.AcroFields;
fields.SetField(“field1”, “Hello World!”);

//Flatten and close
stamper.FormFlattening = true;
stamper.Close();

//If you’re writing to a file, you’re done here. If you want to write to the browser, use the code below.

Byte[] byteArray = ms.ToArray();
ms.Flush();
ms.Close();
Response.BufferOutput = true;
Response.Clear();
Response.ClearHeaders();
string timestamp = DateTime.Now.ToString(“MMddyyyy_HHmmss”);
Response.AddHeader(“Content-Disposition”, “attachment; filename=PDF_” + timestamp + “.pdf”);
Response.ContentType = “application/pdf”;
Response.BinaryWrite(byteArray);
Response.End();

.NET 3.5, Entity Framework, Add Function Import…

Gahhh!…? If your project is built on .NET 3.5 and you try to create an Entity Framework function using the “Add Function Import…” tool for a stored procedure that doesn’t return an EF object (instead return a scalar or nothing), the code for the function is not generated. Basically, all your spocs have to return an equivalent of one of your data objects. It all works fine if I use .NET 4.0 but I don’t think our servers have the framework installed yet. What to do…what to do…

Installing SSL on IIS7 with host headers

I have one wildcard SSL certificate and needed to use it on multiple subdomains. The IIS7 UI doesn’t allow you to specify the host header when configuring an ssl binding. The only way I found to do it was by using appcmd from the command prompt. The command works as such:

appcmd set site /site.name:"<IISSiteName>" /+bindings.[protocol='https',bindingInformation='*:443:<hostHeaderValue>']

<IISSiteName> is the name of your site in IIS. <hostHeaderValue> is the host header you’re trying to bind to.

I found this tidbit on http://www.sslshopper.com/article-ssl-host-headers-in-iis-7.html. According to their steps, you should install the ssl on one site with the admin console first before using appcmd. I’m not sure if this is true. I assume you can use appcmd for all of them.

SQL Named Instance Port Number

Heads up, you probably know the default port for SQL is 1433 but did you know the port is different for a named instance? And this port is dynamically set when you install the server. You can see what it is by looking in the registry. The below registry path is for SQL2008.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL10.(InstanceName)\MSSQLServer\SuperSocketNetLib\TCP\IPAll

There are more details in this article

And if you are using a named instance SQL server, don’t forget to adjust your connection string.

<add name=”MyConnString” connectionString=”Data Source=MyServerName, 51601; Initial Catalog=Northwind;user id=MyUserName;password=SecretPassword” providerName=”System.Data.SqlClient” />

Notice 51601 is the port number.