Signed in as kevin025
| Sign out | Help

Kirk Allen Evans'
Blog

.NET From a Markup Perspective

This Blog

Email
alerts

About

Email

Calendar

May

June 2006

Jul

S

M

T

W

T

F

S

28

29

30

31

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

1

2

3

4

5

6

7

8

Search

Go

Syndication

RSS 2.0

Atom 1.0

Archives

October 2006
(1)

September
2006 (3)

August 2006
(2)

June 2006
(14)

May 2006
(20)

April 2006
(11)

March 2006
(12)

February 2006
(16)

January 2006
(14)

December 2005
(4)

November 2005
(20)

October 2005
(5)

September
2005 (23)

August 2005
(4)

July 2005
(13)

June 2005
(9)

May 2005
(6)

April 2005
(13)

March 2005
(10)

February 2005
(16)

January 2005
(4)

December 2004
(13)

November 2004
(6)

October 2004
(12)

September
2004 (9)

August 2004
(10)

July 2004
(9)

June 2004
(10)

May 2004
(11)

April 2004
(15)

March 2004
(6)

February 2004
(3)

January 2004
(1)

December 2003
(4)

November 2003
(11)

October 2003
(14)

September
2003 (2)

August 2003
(3)

July 2003
(10)

June 2003
(11)

May 2003
(6)

April 2003
(32)

March 2003
(17)

February 2003
(16)

News

Now running Office 2007 Beta 2

Navigation

Home

Photos

Post Categories

.NET
Programming (109)

Atlanta
Microsoft Events (36)

BizTalk
(1)

Braves
Baseball (4)

Life at
Microsoft (38)

Mobile
Development (4)

PDC
2003 (8)

PDC05
(7)

Personal
(17)

Security
(3)

SharePoint
(4)

SQL
Server 2005 (2)

Telecommunications
(16)

UGA
Football (8)

VSTS
(4)

Windows
Workflow Foundation (2)

XML
(40)

XML
Schemas (5)

XML Web
Services (59)

About

Atlanta
Bloggers OPML

Tips for a
Successful Technical Presentation

Recommended Reading

Microsoft CSNA DPE Bloggers

Kirk Allen Evans

Jit Ghosh

Mike Gilbert

Michael Johnson

Deven Kampenhout

Ted Hu

Tito Leverette

Jonathan Wells

.NET Resources

.NET 2.0 QuickStarts

Get
the .NET Framework

.NET
Development Documentation

ASP.NET
Official Site

Windows Forms Official Site

Windows Communication Foundation
Official Site

Windows
Workflow Foundation Official Site

Visual Studio Developer Center

ASMX 2.0 and SchemaImporterExtensions

I like the concept of SchemaImporterExtensions in ASMX 2.0.  As you
import the schema through proxy generation using WSDL.exe, you can generate your
own code to control serialization for the client.

This can be a great tool if you have a particularly nasty interop problem and
the generated proxy code doesn't work.  For instance, Dan Maharry has
been having some problems with the XmlSerializer.  Scott Hanselman
suggested for him to control the serialization on the server side using
IXmlSerializable, but on the client side, I am betting that he sees the reverse
problem.  This is a situation where a SchemaImporterExtension and some
custom generated client-side code can provide a solution.

I combined Yasser
Shohoud's Net Tunes SIE and John
Bristowe's SIE example, and added the ability actually emit a new file that
contains the generated code.  This is the SchemaImporterExtension sample
that I showed on today's
ASMX webcast (also available for on-demand viewing).

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Xml.Serialization;
using System.Xml.Serialization.Advanced;
using System.Xml.Schema;
using System.Xml;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.IO;

namespace CustomerServiceExtensions
{
public class BillItemExtension : SchemaImporterExtension
{

public override string ImportSchemaType(
string name, string ns, XmlSchemaObject context,
XmlSchemas schemas, XmlSchemaImporter importer,
CodeCompileUnit compileUnit, CodeNamespace mainNamespace,
CodeGenerationOptions options, CodeDomProvider codeProvider)
{
ConsoleColor defaultbgColor = Console.BackgroundColor;
ConsoleColor defaultfgColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("\tOrderExtension called for name = " + name + " and namespace = " + ns);
Console.ForegroundColor = defaultfgColor;

if (name.Equals("Customer") && ns.Equals("http://contoso"))
{
Console.BackgroundColor = ConsoleColor.Blue;
Console.WriteLine();
Console.WriteLine("\t\tExtension matched for Customer!");
Console.WriteLine();
Console.BackgroundColor = defaultbgColor;

mainNamespace.Imports.Add(new CodeNamespaceImport("Msdn.Web.Samples"));
return "Customer";
}
if (name.Equals("BillItem") && ns.Equals("http://contoso"))
{
Console.BackgroundColor = ConsoleColor.Blue;
Console.WriteLine();
Console.WriteLine("\t\tExtension matched for BillItem!");
Console.WriteLine();
Console.BackgroundColor = defaultbgColor;

mainNamespace.Imports.Add(new CodeNamespaceImport("Msdn.Web.Samples"));
return "OrderDetails";
}
if (name.Equals("ArrayOfBillItem") && ns.Equals("http://contoso"))
{
Console.BackgroundColor = ConsoleColor.Blue;
Console.WriteLine();
Console.WriteLine("\t\tExtension matched for ArrayOfBillItem!");
Console.WriteLine();
Console.BackgroundColor = defaultbgColor;

mainNamespace.Imports.Add(new CodeNamespaceImport("Msdn.Web.Samples"));

CodeTypeDeclaration speaker = new CodeTypeDeclaration("Person");
mainNamespace.Types.Add(speaker);

CodeMemberField firstNameField = new CodeMemberField(
new CodeTypeReference(
typeof(string)),
"_firstName");
speaker.Members.Add(firstNameField);

CodeMemberProperty firstNameProperty = new CodeMemberProperty();
firstNameProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final;
firstNameProperty.GetStatements.Add(new CodeMethodReturnStatement(
new CodeFieldReferenceExpression(
new CodeThisReferenceExpression(),
"_firstName")));
firstNameProperty.Name = "FirstName";
firstNameProperty.SetStatements.Add(new CodeAssignStatement(
new CodeFieldReferenceExpression(
new CodeThisReferenceExpression(),
"_firstName"),
new CodePropertySetValueReferenceExpression()));
firstNameProperty.Type = new CodeTypeReference(typeof(string));
speaker.Members.Add(firstNameProperty);

CodeMemberField surnameField = new CodeMemberField(
new CodeTypeReference(
typeof(string)),
"_surname");
speaker.Members.Add(surnameField);

CodeMemberProperty surnameProperty = new CodeMemberProperty();
surnameProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final;
surnameProperty.GetStatements.Add(new CodeMethodReturnStatement(
new CodeFieldReferenceExpression(
new CodeThisReferenceExpression(),
"_surname")));
surnameProperty.Name = "Surname";
surnameProperty.SetStatements.Add(new CodeAssignStatement(
new CodeFieldReferenceExpression(
new CodeThisReferenceExpression(),
"_surname"),
new CodePropertySetValueReferenceExpression()));
surnameProperty.Type = new CodeTypeReference(
typeof(string));
speaker.Members.Add(surnameProperty);

System.IO.StreamWriter writer = new StreamWriter("customCode.cs");

codeProvider.GenerateCodeFromCompileUnit(compileUnit,writer, null);
Console.WriteLine("\n\nWriting file customCode.cs\n\n");
writer.Flush();
writer.Close();
return "ArrayOfBillItem";
}

return null;
}
}
}

You can see in the generated code that you have the ability to emit the code
to a file.  When you run WSDL.exe, the code will be generated in the same
directory as the SoapHttpClientProtocol generated type.  The generated code
looks like this:

//------------------------------------------------------------------------------
//
// This code was generated by a tool.
// Runtime Version:2.0.50727.42
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
//------------------------------------------------------------------------------

using Msdn.Web.Samples;

public class Person {

private string _firstName;

private string _surname;

public string FirstName {
get {
return this._firstName;
}
set {
this._firstName = value;
}
}

public string Surname {
get {
return this._surname;
}
set {
this._surname = value;
}
}
}

The lesson here is that you can generate whatever serialization code you
want, and SchemaImporterExtensions can provide a nice way of getting around some
of the interop problems that you can still face between platforms.

I am looking forward to broader adoption of the Indigo approach of
DataContract / DataMember to get rid of most of the interop problems that are in
the wild today.

Published Tuesday, June 13, 2006 6:46 PM by kaevans
Filed
Under: .NET
Programming, XML,
XML Web
Services, XML
Schemas

Comments

#
SchemaImporterExtension Links

Sunday, July 16, 2006
5:43 PM by David Strommer

#
SchemaImporterExtension Links

Sunday, July 16, 2006
6:52 PM by David Strommer

New Comments to this post are disabled