At our product, we have a client Silverlight part and server-code part, which contains a lot of WCF methods. We don’t use ASP.NET Compatible mode, because we want to leave an opportunity to deploy server part to server without web-server role (without IIS). Really, I don’t know why we chose this way, because all of our installations at the current moment are on IIS. But we have what we have, so we don't have ASP.NET Compatible mode, and as an expected result, we can’t get HttpContext.Current
instance at server WCF methods. One of WCF Services is a RESTful service, which at his methods returns report files, so it can handle GET
-queries from browsers. This is standard code:
WebOperationContext context = WebOperationContext.Current;
context.OutgoingResponse.ContentLength =
reportBytes.Length;context.OutgoingResponse.ContentType = "application/pdf";
context.OutgoingResponse.Headers.Set("content-disposition",
"attachment;filename=" + fileName);
But we have a problem. Some files contain spaces at their names, and different browsers handle these names by their ways. First problem was: if variable filename contains name like “file with spaces.pdf”, then FireFox will show us only “file”, we solved this problem easily, we need to surround file name with quotes (Really, I don’t know how many times I have been writing this code and always get the same problems):
context.OutgoingResponse.Headers.Set("content-disposition",
"attachment;filename=\"" + fileName + "\"");
Internet Explorer has its own way to handle filenames with spaces. It replaces spaces with symbol ‘_’. I was trying to solve this problem with this code:
filename = HttpUtility.UrlPathEncode(filename);
After this line variable filename will has value “filename%20with%20spaces.pdf” and Internet Explorer now saves file with correct name, but FireFox leave %20 instead of spaces. So I need a way to get information at server code which browser asked file. I wrote method IsInternetExplorer
:
private bool IsInternetExplorer()
{
WebOperationContext context = WebOperationContext.Current;
if (context != null)
{
string userAgentInfo = context.IncomingRequest.Headers["User-Agent"];
if (userAgentInfo != null)
return userAgentInfo.Contains("MSIE");
}
return false;
}
So I place plug for Internet Explorer in server code:
if (IsInternetExplorer())
filename = HttpUtility.UrlPathEncode(filename);
It was a surprise for me, that I couldn’t find a way to get browser version in internet. But I knew that should be the way to get user-agent string from request. At first, I wrote realization with OperationContext
:
private bool IsInternetExplorer()
{
OperationContext context = OperationContext.Current;
HttpRequestMessageProperty httpRequest =
context.IncomingMessageProperties["httpRequest"] as HttpRequestMessageProperty;
if (httpRequest != null)
{
string userAgentInfo = httpRequest.Headers["User-Agent"];
if (userAgentInfo != null)
return userAgentInfo.Contains("MSIE");
}
return false;
}
But then, I remembered about WebOperationContext
. I think that WCF is not transparent. I will try in future to learn more about WCF and maybe will try to pass MS exam about WCF.