using System; using System.Net; namespace MyApplication { public class MyFixedHTTPService : MyService { protected override WebRequest GetWebRequest(Uri uri) { HttpWebRequest w = base.GetWebRequest(uri) as HttpWebRequest; w.ProtocolVersion = HttpVersion.Version10; return w; } } }and then use this class to call your service. This forces the proxy to use HTTP 1.0. The best thing about the subclassing approach is that you can simply regenerate the proxy class if you need to, while still retaining your modifications

Motto: "Talk is cheap, show me the code!"
This blog attempts to be a collection of how-to examples in the Microsoft software stack - things that may take forever to find out, especially for the beginner. I see it as my way to return something to the Microsoft community in exchange for what I learned from it.
28 February 2008
Forcing a web service proxy to use a specific http version
23 February 2008
Calling a WCF service from Javascript
In a previous post I pointed out how to call an ASP.NET ASMX web service from javascript in the browser. Although this still works fine, the world has moved on to .NET 3.5 and WCF services have now replaced ASMX services. Luckily, these are also callable from javascript although the procedure is now a little bit different. In this sample I presume you can use Visual Studio 2008 and know a little about WCF.
1. Create an empty solution, and add a WCF service library to it
We'll call the solution JSONWCFTest, and the library JSONServices.2. Add a data contract
using System.Collections.Generic; using System.Runtime.Serialization; namespace JSONServices { [DataContract] public class SampleDataObject { public SampleDataObject(int NewId, string NewName) { Id = NewId; Name = NewName; } [DataMember] public int Id { get; set; } [DataMember] public string Name { get; set; } } }
3. Add service contract
Add an interface IJSONService with the following methods using System.Collections.Generic; using System.ServiceModel;namespace JSONServices { [ServiceContract(Namespace="http://DotNetByExample/JSONDemoService")] public interface IJSONService { [OperationContract] SampleDataObject GetSingleObject(int id, string name); [OperationContract] ICollection GetMultipleObjects(int number); } }
4. Add an implementing class
Implement the service contract like thisSystem.Collections.Generic; namespace JSONServices { public class JSONService : IJSONService { public SampleDataObject GetSingleObject(int id, string name) { return new SampleDataObject(id, name); } public ICollection<SampleDataObject> GetMultipleObjects(int number) { List<SampleDataObject> list = new List<SampleDataObject>(); for (int i = 0; i < number; i++) { list.Add(new SampleDataObject(i, "Name" + i)); } return list; } } }So far, this is very basic WCF stuff. Nothing special here.
5. Add new web application
Add a new project of type "ASP.NET Web Application" to the solution. Call it JSONTestApp. Add a reference to the JSONWCFTest project.6. Add a SVC file to the web application
This part is a bit awkward. Choose "Text File", and name it "AjaxService.svc". Then open the file, and enter the following code<%@ServiceHost language="C#" debug="true" Service="JSONServices.JSONService"It may be tempting to add an "Ajax-enabled WCF service" to the project but this creates its own operation contract, and in this example I want to simulate the situation in which I re-use an already existing operation contract implemented in a separate service library.
Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory"%>
7. Check the javascript interface
Basically, you are done now. Your service is hosted callable from javascript. You can check right-clicking on AjaxService.svc, and you will now see a web page that will say something like "This is a Windows© Communication Foundation service. Metadata publishing for this service is currently disabled." and a lot things more. You can check the javascript interface by adding "/jsdebug" to the url displayed in your browser, in my case this is "http://localhost:1781/AjaxService.svc/jsdebug". This shows the dynamically generated javascript proxy that you can call in your client code:Type.registerNamespace('dotnetbyexample.JSONDemoService'); dotnetbyexample.JSONDemoService.IJSONService=function() { dotnetbyexample.JSONDemoService.IJSONService.initializeBase(this); this._timeout = 0; this._userContext = null; this._succeeded = null; this._failed = null; } dotnetbyexample.JSONDemoService.IJSONService.prototype={ _get_path:function() { var p = this.get_path(); if (p) return p; else return dotnetbyexample.JSONDemoService.IJSONService._staticInstance.get_path();}, GetSingleObject:function(id,name,succeededCallback, failedCallback, userContext) { /// <param name="id" type="Number">System.Int32</param> /// <param name="name" type="String">System.String</param> /// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param> /// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param> /// <param name="userContext" optional="true" mayBeNull="true"></param> return this._invoke(this._get_path(), 'GetSingleObject',false,{id:id,name:name},succeededCallback,failedCallback,userContext); }, GetMultipleObjects:function(number,succeededCallback, failedCallback, userContext) { /// <param name="number" type="Number">System.Int32</param> /// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param> /// <param name="failedCallback" type="Function" optional="true" TomayBeNull="true"></param> /// <param name="userContext" optional="true" mayBeNull="true"></param>Note: FireFox displays the javascript directly in the browser; for security reasons, Internet Explorer wants to download it to a file rather than display it, but after saving it and opening it in a text editor you will see the text above. As you can see this contains a lot of plumbing - and this is only the top part - but I emphasized the parts that are interesting right now: the name of the object that you need to call from javascript (dotnetbyexample.JSONDemoService.IJSONService) and the methods, which have - surprise, suprise - exactly the same name as their C# server-side counterparts. From here on, the procedure is pretty much the same as we were used to when calling asmx webservices from javascript:
8. Add an Web Form to the Web Application
Call it TestForm1.aspx9. Add a script manager and a reference
Add a script manager to the form, right below the form tag, and make a reference to the AjaxService.svc file:<form id="form1" runat="server"> <asp:scriptmanager runat="server"> <services> <asp:ServiceReference Path="AjaxService.svc" /> </services> </asp:scriptmanager>
10. Add some user interface elements to call the service
Right below the script reference, add the following code:<div> ID<asp:TextBox ID="tbId" runat="server">21</asp:TextBox> Name<asp:TextBox ID="tbName" runat="server">John Doe</asp:TextBox><br /> <asp:Button ID="btnSelect" runat="server" Text="SingleSelect" UseSubmitBehavior="False" OnClientClick="CallSingle(); return false;"/> </div> <div id="result1"></div>
11. Add Javascript code
Add some javascript code to call the WCF service and process the results. Place this inside the head-tag, below the title tag:<script type ="text/javascript"> function CallSingle() { dotnetbyexample.JSONDemoService.IJSONService.GetSingleObject( document.getElementById("tbId").value, document.getElementById("tbName").value, CallBackSingle ); } function CallBackSingle( WebServiceResult ) { resultDiv = document.getElementById("result1"); resultDiv.innerHTML = "You entered: id = " + WebServiceResult.Id + " name = " + WebServiceResult.Name; } </script>Notice again that calling a WCF method from javascript works the same as when using asmx services: one extra parameter at the end of the list is required, which is the callback. This is a function that is called upon receiving the result from the server - the server method result is put into the single parameter of the callback.
12. Run the test page
Run Test1Form.aspx. You should be able to input and numerical id and a alphanumeric name, which are sent to the server, and returned back to you as and SampleObject.13. Deploying WCF services in IIS
This all works fine when running it in Cassini, but when you want to host it in IIS, you will need to take care two things. First, you will need to ensure that IIS and WCF are correctly installed and registered. If IIS does not seem to want to cough up your SVC files (you can check that by trying http://<your host here>/<your sitename here>/AjaxService.svc), try running the command ServiceModelReg.exe /i /x from %WINDIR%\Microsoft.NET\Framework\v3.0\Windows Communication Foundation. Restart IIS after running this command. Second, if you created a default ASP.NET 2.0 website, you may run into this error message:IIS specified authentication schemes 'IntegratedWindowsAuthentication, Anonymous', but the binding only supports specification of exactly one authentication scheme. Valid authentication schemes are Digest, Negotiate, NTLM, Basic, or Anonymous. Change the IIS settings so that only a single authentication scheme is used.To fix this, right-click the website in your IIS manager and choose "properties". Then click the "Directory" tab, click the "Edit" button in the "Anonymous access and authentication control" area. You will see that both Anonymous access and Integrated Windows Authentication are selected. Unselect one of them, then restart IIS. After that, the application should work smoothly.
Concluding remarks
Calling WCF services from javascript is even simpler than calling asmx services - you don't even have to mark a service as [ScriptService] anymore, you just put an .svc file into your web site with four lines of code, make a reference to an existing service library and you're done. The sample described here does not use the IJSONService.GetMultipleObjects method, but you can download a the complete source code which includes a second test page that does. Notice that although GetMultipleObjects returns a ICollection14 January 2008
Compacting C# code using implicit properties, object initialization and lambda expressions
public class Person { string _firstName; string FirstName { get { return _firstName; } set { _firstName = value; } } string _lastName; string LastName { get { return _lastName; } set { _lastName = value; } } DateTime _birthDate; DateTime BirthDate { get { return _birthDate; } set { _birthDate = value; } } }To create a list of these objects would be something like
List<Person> opList = new List<Person> Person p1 = new Person(); p1.FirstName = "Joost"; p1.LastName = "van Schaik" p1.BirthDate = new DateTime( 1969,06,03); opList.Add( p1); // etc.To make things easier for you class user you could provide it with constructors, but as the numbers of properties grow, so does the number of (potential) constructors. To actually do something with the resulting list, you could do a foreach( OPerson p in opList) etc, or write something like this:
l.ForEach(delegate(Person p) { Console.WriteLine(p.FirstName); });It works but I always thought this to be a bit of an awkward way of making predicates Implicit properties For a class as simple as the Person, you don't need to define 'backing variables anymore. These are inferred from code. Therefore, we can refactor the person class like this:
public class Person { public Person() { } public string FirstName { get; set; } public string LastName { get; set; } public DateTime BirthDate { get; set; } }That's rather compact, I'd say Object initalization The creation and initalization of a object can be written as follows:
Person p1 = new Person { FirstName = "Joost", LastName = "van Schaik", BirthDate=new DateTime( 1969, 06, 03)});And while we are at it, the creation of a list of persons could be even simpler:
List<Person> l= new List<Person> { new Person { FirstName = "Joost", LastName = "van Schaik", BirthDate=new DateTime( 1969, 06, 03)}, new Person { FirstName = "John", LastName = "Doe", BirthDate = new DateTime(1970, 01, 01) }, new Person { FirstName = "Michel", LastName = "van Schaik", BirthDate = new DateTime(1970, 12, 25) } };Lambda expressions And finally, picking out the first name myself and my family members would require only one line:
List<Person> vanSchaik = l.FindAll(p => p.LastName == "van Schaik");And writing them out, too
vanSchaik.ForEach(p => Console.WriteLine(p.FirstName));Conclusion The new features of C# can be used to make code more compact and better readable at the same time. Lambda expressions is certainly something you need to get used to reading, but for simple expressions they make life a heck of a lot easier. Complex expressions are hard to understand and read, though. Keep in mind that the next programmer may have a hard time reading your code, so don't use it just for the sake of it.
26 November 2007
String extension methods
In general, we recommend that you implement extension methods sparingly and only when you have to. Whenever possible, client code that must extend an existing type should do so by creating a new type derived from the existing type.Full article Then try to make a List<> and bring up the Intellisense box. You will see 40-50 new methods, and by now you will guess they are all extension methods. Practiced what thy preached, Microsoft! Anyway, if Microsoft makes a lot of extension methods, so can we. We can now finally get rid of our 'utility' classes and make something like this:
namespace LocalJoost.Utilities
{
public static class StringExtensions
{
public static string Reverse(this string s)
{
StringBuilder builder = new StringBuilder();
for (int i = s.Length - 1; i >= 0; i--)
{
builder.Append(s.Substring(i, 1));
}
return builder.ToString();
}
}
}
And then we can do something like this:
string test = "Hello hello"; string reversed = test.Reverse();The string "reversed" will now contain the string "olleh olleH". Notice the "this" keyword before the string s in method Reverse of class StringExtensions - that is the thing that defines Reverse as an extension method of string. The only further requirements are that both class and method implementing the extension are static.
19 November 2007
Creating a simple proxy
void ProcessProxyRequest( string request, HttpResponse response) { HttpWebRequest webRequest = HttpWebRequest.Create(request) as HttpWebRequest; // Important! Keeps the request from blocking after the first time! webRequest.KeepAlive = false; webRequest.Credentials = CredentialCache.DefaultCredentials; using (HttpWebResponse backendResponse = (HttpWebResponse)webRequest.GetResponse()) { Stream receiveStream = backendResponse.GetResponseStream(); // Clear whatever is already sent response.Clear(); response.ClearContent(); response.ClearHeaders(); // Copy headers // Check if header contains a contenth-lenght since IE // goes bananas if this is missing bool contentLenghtFound = false; foreach (string header in backendResponse.Headers) { if (string.Compare(header, "CONTENT-LENGTH", true) == 0) { contentLenghtFound = true; } response.AppendHeader(header, backendResponse.Headers[header]); } // Copy content byte[] buff = new byte[1024]; long length = 0; int bytes; while ((bytes = receiveStream.Read(buff, 0, 1024)) > 0) { length += bytes; response.OutputStream.Write(buff, 0, bytes); } // Manually add content-lenght header to satisfy IE if (!contentLenghtFound) { response.AppendHeader("Content-Length", length.ToString()); } receiveStream.Close(); backendResponse.Close(); response.Flush(); response.Close(); } }Now of course, in the Page_Load you have to do something first:
protected void Page_Load(object sender, EventArgs e) { string requestInsideDMZ = "http://somewhereinyourdmz/somepage.aspx"; ProcessProxyRequest( requestInsideDMZ, Response); }If the user accesses MyProxyPage.aspx he gets the contents of http://somewhereinyourdmz/somepage.aspx instead.
02 November 2007
Expanding the length of JSON data returned from ASP.NET web services
[WebMethod] public string HelloWorld( string ToSomeone) { StringBuilder b = new StringBuilder(); while (b.Length < 50000) { b.AppendFormat("Hello World {0}. ", ToSomeone); } return b.ToString(); }You get al LOT of "Hello Worlds". Now change 50000 into 200000... you get no error message, but in fact, you get no response at all. To solve this, you need to delve into your web.config. Make sure the JSON configuration declaration at the top looks like this. I highlighted the important part:
<configSections>
<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
<sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere" />
<section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
<section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
</sectionGroup>
</sectionGroup>
</sectionGroup>
</configSections>
This may look a bit intimidating, but just copy it.
In the system.web part you can define the following tag:
<system.web.extensions> <scripting> <webServices> <jsonSerialization maxJsonLength="999999999"/> </webServices> </scripting> </system.web.extensions>And there you go. The number 999999999 is the absolute max value - so if you send stuff to your client longer than that, you have to think of something else. But for the mapping applications I made on Google Maps this works fine. Bear in mind that sending VERY large portions of data can degrade your user experience considerably, although the asynchronous nature of the ASP.NET JSON service might diminish that problem. By the way, in the latest templates for ASP.NET Ajax enabled web sites the whole configuration declaration is already included, as well as the declaration for the json serialization - but it is commented out. It looks something like this.
<!-- Uncomment this line to customize maxJsonLength and add a custom converter -->
<!--
<jsonSerialization maxJsonLength="500">
<converters>
<add name="ConvertMe" type="Acme.SubAcme.ConvertMeTypeConverter"/>
</converters>
</jsonSerialization>
-->
You have to delete the part that I printed in italics, because that is just an example that does not point to an actual class
29 October 2007
The right way of accessing Master page properties from a child page
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="MyDemoMaster.master.cs" Inherits="MasterPageDemo.MyDemoMaster" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> <asp:button id="btnWithText" runat="server" text="Button"> <asp:contentplaceholder id="ContentPlaceHolder1" runat="server"> </asp:ContentPlaceHolder> </div> </form> </body> </html>In the Master Page, you can create a property like this:
public string ButtonText { get { return this.btnWithText.Text; } set { this.btnWithText.Text = value; } }Unfortunately, if you try to find the property "Master.ButtonText" in the childpage, it won't be available since the "Master" property is of type System.Web.UI.Page, and that does not contain properties of your derived class "MyDemoMaster" This, of course, can be solved by changing the Page_Load of the child page like this:
protected void Page_Load(object sender, EventArgs e) { MyDemoMaster m = Master as MyDemoMaster; m.ButtonText = "My button text"; }Congratulations. Your button shows the right text. And you have succeeded into locking your child page to a single master. Your web page will not run when you try to use another master page. Go back to programming class 101 and you don't get any cookies today ;-) The right solution is: create an interface like this:
namespace MasterPageDemo { public interface IButtonText { string ButtonText { get;set;} } }Open the code behind file of your Master Page and let it implement the interface:
public partial class MyDemoMaster : System.Web.UI.MasterPage, IButtonText
{
protected void Page_Load(object sender, EventArgs e)
{
}
public string ButtonText
{
get { return this.btnWithText.Text; }
set { this.btnWithText.Text = value; }
}
}
And then you make the Page_Load of the child page like this
protected void Page_Load(object sender, EventArgs e) { IButtonText m = Master as IButtonText ; if( m != null ) m.ButtonText = "My button text"; }Now the Master Page and Child Page are no longer coupled by name. Any Master Page implementing the IButtonText interface may be used as a Master Page for your child. Checking if it can be casted by testing m != null is a nice encore.