RadChart with .NET MVC

I have a webform app that I converted to a webform/mvc hybrid. Everything was fine until I tested the Telerik RadCharts on the existing webform pages. It had worked before the conversion. Now whenever the chart was supposed to load, I was confronted with this error message:

Error loading RadChart image. You may also wish to check the ASP.NET Trace for further details. Display stack trace?

Clicking “OK” simply took me to a 404 page. I did notice the url of this was http://localhost:11239/reports/ChartImage.axd?UseSession=true&ChartID=139df24e-1578-44d3-988b-c66f2d7df98c_chart_ctl00$MainContent$ReportChart1&imageFormat=Png&random=0.725656411482793

Somehow MVC routing disrupted the RadChart handler. To fix this, you need to explicitly define the HttpHanderUrl property of the RadChart.

ReportChart1.HttpHandlerUrl = ResolveUrl("~/ChartImage.axd");

That should fix it!

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.

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.

C# and VB.NET in the same App_Code folder

I learned something cool today. I’m taking over a site that’s been written in VB.NET. While making some major modifications, I had to create a few new util classes. The problem is, the existing classes in the App_Code folder was written in VB.NET and I like to code in C#. If you try to compile a site that has two different languages in the App_Code directory, it won’t work. I found this article that says it can be done it just two steps. The trick is to create two subdirectories in App_Code; one to house each language; then edit your web.config to let the compiler know what to expect.

In an ideal environment this works. The website will compile fine. But I ran into another issue after doing this. After I created my two subdirectories (CS_Code and VB_Code), I moved the existing VB classes into VB_Code. The problem is, there are xsd files that I need to leave in the App_Code folder. These DAL files need to be in the root App_Code directory because it needs to be accessed by all the classes (VB and C#). But after I moved the VB classes into VB_Code, the VB classes can no longer see the xsd classes.

I feel like this is an issue that can easily be resolved but it’s past midnight and maybe my mind isn’t thinking straight. Also keep in mind that the project is a Website and not a Web Application. I’ve ran into issues in the past where the nuances between the two made a world of difference. It’s shame this project is due tomorrow. Comment/suggestions welcome*.

*and encouraged

Ensuring image quality when resizing in .NET

I needed to create a web page where users can upload photos. In turn, these photos will be resized into three different dimensions (small, medium, and large) and displayed on the site. The original code I was using to resize the images was pretty much hit or miss. Often times the resulting image was blurry and/or pixelated. The original code took the file from the file upload control and saved it as a bitmap. Then it used the GetThumbnailImage method to resize the image. Here is a sample.

System.Drawing.Image.GetThumbnailImageAbort myCallBack = new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallBack);
System.Drawing.Bitmap bitmap = new Bitmap(fileUpload.InputStream);
System.Drawing.Image newImage = bitmap.GetThumbnailImage(600, 800, myCallBack, IntPtr.Zero);
newImage.Save(“c:\resizedImage.jpg”);
newImage.Dispose();

private static bool ThumbnailCallback()
{
return false;
}

The callback method is called if the resize fails but I’m not sure what the IntPtr.Zero does. VS’s intellisense states “Must be System.IntPtr.Zero”, so who am I to argue. The code is very simple but not very effective. Today I found a better method. This time using an Image object instead and resizing it with the Graphics class. Finally, I use the Bitmap object to save the image.

System.Drawing.Image image = Bitmap.FromStream(file.InputStream);
System.Drawing.Imaging.ImageFormat imageFormat = image.RawFormat;
Size size = new Size(600, 800);
bitmap = new Bitmap(image, size.Width, size.Height);

Graphics resizer;
resizer = Graphics.FromImage(bitmap);
resizer.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
resizer.DrawImage(image, 0, 0, size.Width, size.Height);

bitmap.Save(“c:\resizedImage.jpg”, imageFormat);
bitmap.Dispose();
image.Dispose();

There are a few important key elements here. First is the InterpolationMode. HighQualityBicubic gives you the best quality but I find HighQualityBilinear decreases the size by at least a few KB and I couldn’t tell the difference between the two just by looking at it. Also, when using bitmap.Save(), the image format parameter is not required but it makes all the difference. For example, I resized a 2112 x 2816 pixel to 600 x 800. If I didn’t specify the image format the size was reduced from 2.2 MB to 1.1 MB. When I did specify the image format, the resulting file size was 58 KB! Again, I could barely tell the difference between the two resulting images. And finally, always clean up after yourself. Dispose of objects you no longer need, especially if they deal with streams.

WebDAV and recurring events in Exchange 2003

I’m in the process of building a web app to pull calendar events from Exchange 2003 and display them on a page. With some research and a lot of trial and error, I was able to put together bit and pieces of examples on the web and get most of it done. The only problem is that recurring events were not being pulled. It turns out that if a recurring event is schedule to recur ad infinitum, the WebDAV query will not retrieve the event unless a start date and end date is specified. Below is part of the code.

public void Authenticate(string authUri, string destinationUri, string username, string password)

{

// Create the web request body:

string body = string.Format(“destination={0}&username={1}&password={2}”, destinationUri, username, password);

byte[] bytes = Encoding.UTF8.GetBytes(body);

// Create the web request:

HttpWebRequest request = (HttpWebRequest)System.Net.WebRequest.Create(authUri);

request.Method = “POST”;

request.ContentType = “application/x-www-form-urlencoded”;

request.CookieContainer = new CookieContainer();

request.ContentLength = bytes.Length;

// Create the web request content stream:

using (Stream stream = request.GetRequestStream())

{

stream.Write(bytes, 0, bytes.Length);

stream.Close();

}

// Get the response & store the authentication cookies:

HttpWebResponse response = (HttpWebResponse)request.GetResponse();

if (response.Cookies.Count < 2)

throw new AuthenticationException(“Login failed. Is the login / password correct?”);

cookies = new CookieContainer();

foreach (Cookie myCookie in response.Cookies)

{

cookies.Add(myCookie);

}

response.Close();

}

public List<CalendarEvent> GetCalendar(string uri, DateTime startDate, DateTime endDate)

{

List<CalendarEvent> eventList = new List<CalendarEvent>();

HttpWebRequest request;

WebResponse response;

byte[] bytes;

// Note that deep traversals don’t work on public folders. In other words, if you

// need to dig deeper you’ll need to split your query into multiple requests.

string format =

@”<?xml version=””1.0″”?>” +

@”<D:searchrequest xmlns:D = “”DAV:””>” +

@”<D:sql>” +

@”SELECT “”urn:schemas:calendar:dtstart””, ” +

@”””urn:schemas:calendar:dtend””, ” +

@”””urn:schemas:calendar:location””, ” +

@”””urn:schemas:httpmail:subject””, ” +

@”””urn:schemas:httpmail:htmldescription””, ” +

@”””urn:schemas:httpmail:to””, ” +

@”””urn:schemas:calendar:organizer””, ” +

@”””DAV:parentname”” ” +

@”FROM ” +

@”Scope(‘SHALLOW TRAVERSAL OF “”{0}””‘) ” +

@”WHERE ” +

@”NOT “”urn:schemas:calendar:instancetype”” = 1 ” +

@”AND “”DAV:contentclass”” = ‘urn:content-classes:appointment’ ” +

@”AND “”urn:schemas:calendar:dtstart”” &gt;= ‘{1}’ ” +

@”AND “”urn:schemas:calendar:dtend”” &lt;= ‘{2}’ ” +

@”</D:sql>” +

@”</D:searchrequest>”;

string fullQuery = String.Format(format, uri, DateTime.Now.AddYears(-1).ToString(“yyyy/MM/dd”), DateTime.Now.AddYears(1).ToString(“yyyy/MM/dd”));

bytes = Encoding.UTF8.GetBytes(String.Format(fullQuery, uri, startDate, endDate));

// Use the authorization cookies we stored in the authentication method.

request = (HttpWebRequest)HttpWebRequest.Create(uri);

request.CookieContainer = cookies;

request.Method = “SEARCH”;

request.ContentLength = bytes.Length;

request.ContentType = “text/xml”;

using (Stream requestStream = request.GetRequestStream())

{

requestStream.Write(bytes, 0, bytes.Length);

requestStream.Close();

}

response = (HttpWebResponse)request.GetResponse();

using (Stream responseStream = response.GetResponseStream())

{

// Parse the XML response to find the data we need.

XmlDocument document = new XmlDocument();

document.Load(responseStream);

XmlNodeList subjectNodes = document.GetElementsByTagName(“e:subject”);

XmlNodeList startTimeNodes = document.GetElementsByTagName(“d:dtstart”);

XmlNodeList endTimeNodes = document.GetElementsByTagName(“d:dtend”);

XmlNodeList organizerNodes = document.GetElementsByTagName(“d:organizer”);

XmlNodeList bodyNodes = document.GetElementsByTagName(“e:htmldescription”);

XmlNodeList locationNodes = document.GetElementsByTagName(“d:location”);

XmlNodeList toNodes = document.GetElementsByTagName(“e:to”);

string bodyStart = “<!– Converted from text/rtf format –>\r\n\r\n”;

string bodyEnd = “\r\n\r\n</BODY”;

for (int index = 0; index < subjectNodes.Count; index++)

{

string subject = subjectNodes[index].InnerText;

string organizer = HttpContext.Current.Server.HtmlEncode(organizerNodes[index].InnerText.Replace(“\””, “”).Replace(“<“, “(“).Replace(“>”, “)”));

DateTime startTime = DateTime.Parse(startTimeNodes[index].InnerText);

DateTime endTime = DateTime.Parse(endTimeNodes[index].InnerText);

string body = bodyNodes[index].InnerText;

string location = locationNodes[index].InnerText;

//CalendarEvent is my custom class

CalendarEvent ev = new CalendarEvent();

ev.StartTime = startTime;

ev.EndTime = endTime;

ev.Subject = subject;

ev.Organizer = organizer;

ev.Body = body;

ev.Location = location;

eventList.Add(ev);

}

}

response.Close();

return eventList;

}

Modal windows on the web

I’ve been in web development for a while now and one thing I do notice is that web sites are headed towards a desktop user experience. One of the key UI elements is the modal window. You know, the that little window that won’t let you do anything until you respond to it. I’ve been having to use it in our web projects more and more. Usually, this effect is comprised of CSS and Javascript. Up till recently, I’ve only had a change to fumble my way trying to get all the pieces together for the correct effect. Then I would run out of time and end up using the ASP.Net AJAX modal control or another RAD control. I usually don’t have a problem with these controls but sometimes, I just want something lightweight with just enough functionality to do what I need.

The other day I stumbled upon Jeff’s blog about the modal window.
It was almost everything I needed.

My modal windows is:


<div id="modalPage">
<div class="modalBackground">
</div>
<div class="modalContainer">
<div class="modal">
</div>
</div>
</div>

My styles are:


.modalPage
{
display: none;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
position:fixed;

}
.modalBackground {
filter: Alpha(Opacity=40);
-moz-opacity:0.4;
opacity: 0.4;
width: 100%;
height: 100%;
background-color: #999999;
position: absolute;
z-index: 500;
top: 0px;
left: 0px;

}
.modalContainer
{
position: absolute;
width: 600px;
left: 50%;
top: 50%;
z-index: 750;

}
.modal
{
background-color: white;
position: relative;
top: -150px;
left: -300px;
z-index: 1000;
width: 600px;
height: 300px;
padding: 0px;
}

And my javascript is

function revealModal(divID)
{
document.getElementById(divID).style.display = "block";
}

function hideModal(divID)
{
document.getElementById(divID).style.display = "none";
}

The only thing that didn’t work for me from Jeff’s code was in the hideModal function. He had two extra lines to ensure the transparent overlay background moved with the window if the user scrolled the page. For me, the gray background remained static and if you were to scroll down, the rest of the page was not covered and could still receive interaction from the mouse. Jeff’s script might not have worked for me because I am running IE 8 Beta 2…although I was in IE 7 compatibility mode. Anyways, the fix for me was pretty simple and it lies in the #modalPage style. All I did was set the position to fixed. That did the trick!

Be warned, the current project I’m working on is an intranet site that will only be viewed on IE so I haven’t tested this fix with FireFox, Safari, or Opera.

HAPPY HALLOWEEN!

System.Net.Mail on GoDaddy.com

Personally I think GoDaddy is great for purchasing domain names. Alright, not great because of all the upsells they make you  go through when buying a domain. The price sure beats Register.com and NetworkSolutions. But I won’t host on GoDaddy for two reasons. First, I don’t like keeping all my eggs in one basket. Regardless of the fact that there are only 2 eggs. Second, I’ve read many stories of hardships with people trying to get their site to work on GoDaddy.

Now I can add myself to the list. It seems like when you are sending emails with System.Net.Mail, you need to hunt for the name of the mail server. The site was for a side project. My function to send the email kept bombing out with a connection timeout error. GoDaddy tech support said to use smtpout.secureserver.net and so I did. For a week I did, and could not figure out why it kept failing. I had to do my own research to find out that the real server is relay-hosting.secureserver.net. Wow! So much for relying on a definitive answer from tech support. Now I’m really never going to host with them.

Dynamically create gradient image

The code below dynamically creates a jpeg with a gradient, saves it to the server, and is assigned to an image object. I used the code below to dynamically generate a bar graph. The reason we append the uniqueVal to the file name is so that if the user is constantly refreshing the graph, the browser won’t pull up a cached image.

using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Drawing;

string uniqueVal = DateTime.Now.Ticks.ToString();
Bitmap bitmap = new Bitmap(180, 15);
Graphics graphics = Graphics.FromImage(bitmap);
LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0,0,180,15), Color.Gainsboro, Color.Blue, 45.0f, false);
graphics.FillRectangle(brush, new Rectangle(0, 0, 180, 15));
string fileName = "gradient" + uniqueVal + ".jpg";
bitmap.Save(Server.MapPath(fileName), ImageFormat.Jpeg);
graphics.Dispose();
bitmap.Dispose();
System.Web.UI.WebControls.Image img = new System.Web.UI.WebControls.Image();
img.ImageUrl = Server.MapPath(fileName);