Finalized WCF ServiceExporter [SPRNET-1001].

Polished WCF integration + QuickStart + Doc.
This commit is contained in:
bbaia
2008-11-09 07:34:12 +00:00
parent bcde9cefa0
commit 8a88b425ee
22 changed files with 918 additions and 593 deletions

View File

@@ -242,8 +242,7 @@
&lt;/object&gt;</programlisting>
<note>
<para>This will be shortened using a custom namespce in the 1.2 final
release</para>
<para>This will be shortened using a custom namespce in a future release</para>
</note>
<para>The value 'serverAppCalculatorEndpoint' refers to the name of an

View File

@@ -2,31 +2,14 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.WcfQuickStart.ClientApp.2008", "src\Spring.WcfQuickStart.ClientApp\Spring.WcfQuickStart.ClientApp.2008.csproj", "{D58B3101-4433-49C5-B41B-51134424FC42}"
EndProject
Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "Spring.WcfQuickStart.Web.2008", "src\Spring.WcfQuickStart.Web.2008\", "{B71CEEE1-9C92-4C79-94BE-46D6D4CDE95A}"
ProjectSection(WebsiteProperties) = preProject
TargetFramework = "3.5"
ProjectReferences = ""
Debug.AspNetCompiler.VirtualPath = "/Spring.WcfQuickStart.Web.2008"
Debug.AspNetCompiler.PhysicalPath = "src\Spring.WcfQuickStart.Web.2008\"
Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\Spring.WcfQuickStart.Web.2008\"
Debug.AspNetCompiler.Updateable = "true"
Debug.AspNetCompiler.ForceOverwrite = "true"
Debug.AspNetCompiler.FixedNames = "false"
Debug.AspNetCompiler.Debug = "True"
Release.AspNetCompiler.VirtualPath = "/Spring.WcfQuickStart.Web.2008"
Release.AspNetCompiler.PhysicalPath = "src\Spring.WcfQuickStart.Web.2008\"
Release.AspNetCompiler.TargetPath = "PrecompiledWeb\Spring.WcfQuickStart.Web.2008\"
Release.AspNetCompiler.Updateable = "true"
Release.AspNetCompiler.ForceOverwrite = "true"
Release.AspNetCompiler.FixedNames = "false"
Release.AspNetCompiler.Debug = "False"
VWDPort = "2637"
DefaultWebSiteLanguage = "Visual C#"
ProjectSection(ProjectDependencies) = postProject
{EEC5B531-104B-44E6-975B-44C0C8973405} = {EEC5B531-104B-44E6-975B-44C0C8973405}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.WcfQuickStart.ServerApp.2008", "src\Spring.WcfQuickStart.ServerApp\Spring.WcfQuickStart.ServerApp.2008.csproj", "{27AAD98C-4281-4DD4-9E20-1371C58C5283}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.WcfQuickStart.ServerWeb.2008", "src\Spring.WcfQuickStart.ServerWeb\Spring.WcfQuickStart.ServerWeb.2008.csproj", "{EEC5B531-104B-44E6-975B-44C0C8973405}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|.NET = Debug|.NET
@@ -47,16 +30,6 @@ Global
{D58B3101-4433-49C5-B41B-51134424FC42}.Release|Any CPU.Build.0 = Release|Any CPU
{D58B3101-4433-49C5-B41B-51134424FC42}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{D58B3101-4433-49C5-B41B-51134424FC42}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{B71CEEE1-9C92-4C79-94BE-46D6D4CDE95A}.Debug|.NET.ActiveCfg = Debug|.NET
{B71CEEE1-9C92-4C79-94BE-46D6D4CDE95A}.Debug|.NET.Build.0 = Debug|.NET
{B71CEEE1-9C92-4C79-94BE-46D6D4CDE95A}.Debug|Any CPU.ActiveCfg = Debug|.NET
{B71CEEE1-9C92-4C79-94BE-46D6D4CDE95A}.Debug|Mixed Platforms.ActiveCfg = Debug|.NET
{B71CEEE1-9C92-4C79-94BE-46D6D4CDE95A}.Debug|Mixed Platforms.Build.0 = Debug|.NET
{B71CEEE1-9C92-4C79-94BE-46D6D4CDE95A}.Release|.NET.ActiveCfg = Debug|.NET
{B71CEEE1-9C92-4C79-94BE-46D6D4CDE95A}.Release|.NET.Build.0 = Debug|.NET
{B71CEEE1-9C92-4C79-94BE-46D6D4CDE95A}.Release|Any CPU.ActiveCfg = Debug|.NET
{B71CEEE1-9C92-4C79-94BE-46D6D4CDE95A}.Release|Mixed Platforms.ActiveCfg = Debug|.NET
{B71CEEE1-9C92-4C79-94BE-46D6D4CDE95A}.Release|Mixed Platforms.Build.0 = Debug|.NET
{27AAD98C-4281-4DD4-9E20-1371C58C5283}.Debug|.NET.ActiveCfg = Debug|Any CPU
{27AAD98C-4281-4DD4-9E20-1371C58C5283}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{27AAD98C-4281-4DD4-9E20-1371C58C5283}.Debug|Any CPU.Build.0 = Debug|Any CPU
@@ -67,6 +40,16 @@ Global
{27AAD98C-4281-4DD4-9E20-1371C58C5283}.Release|Any CPU.Build.0 = Release|Any CPU
{27AAD98C-4281-4DD4-9E20-1371C58C5283}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{27AAD98C-4281-4DD4-9E20-1371C58C5283}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{EEC5B531-104B-44E6-975B-44C0C8973405}.Debug|.NET.ActiveCfg = Debug|Any CPU
{EEC5B531-104B-44E6-975B-44C0C8973405}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EEC5B531-104B-44E6-975B-44C0C8973405}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EEC5B531-104B-44E6-975B-44C0C8973405}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{EEC5B531-104B-44E6-975B-44C0C8973405}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{EEC5B531-104B-44E6-975B-44C0C8973405}.Release|.NET.ActiveCfg = Release|Any CPU
{EEC5B531-104B-44E6-975B-44C0C8973405}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EEC5B531-104B-44E6-975B-44C0C8973405}.Release|Any CPU.Build.0 = Release|Any CPU
{EEC5B531-104B-44E6-975B-44C0C8973405}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{EEC5B531-104B-44E6-975B-44C0C8973405}.Release|Mixed Platforms.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -11,10 +11,10 @@
<spring>
<context>
<!-- Make sure 'http://localhost:2637/Spring.WcfQuickStart.Web/' web application is running -->
<resource uri="assembly://Spring.WcfQuickStart.ClientApp/Spring.WcfQuickStart.Config/Web.xml" />
<!-- Make sure 'http://localhost:2637/Spring.WcfQuickStart.ServerWeb/' web application is running -->
<resource uri="assembly://Spring.WcfQuickStart.ClientApp/Spring.WcfQuickStart.Config/ServerWeb.xml" />
<!-- Make sure 'ServerApp' console application is running and listening. -->
<!-- Make sure 'Spring.WcfQuickStart.ServerApp' console application is running and listening. -->
<resource uri="assembly://Spring.WcfQuickStart.ClientApp/Spring.WcfQuickStart.Config/ServerApp.xml" />
</context>
@@ -42,8 +42,8 @@
</bindings>
<client>
<endpoint name="webCalculatorEndpoint"
address="http://localhost:2637/Spring.WcfQuickStart.Web.2008/Calculator.svc"
<endpoint name="serverWebCalculatorEndpoint"
address="http://localhost:2637/Spring.WcfQuickStart.ServerWeb/Calculator.svc"
binding="basicHttpBinding" bindingConfiguration="basicHttpBinding1"
contract="Spring.WcfQuickStart.ICalculator" />
<endpoint name="serverAppCalculatorEndpoint"

View File

@@ -2,13 +2,13 @@
<objects xmlns="http://www.springframework.net">
<!-- returns ChannelFactory<ICalculator>("calculatorEndpoint").CreateChannel() -->
<object id="webCalculator"
<object id="serverWebCalculator"
type="Spring.WcfQuickStart.ICalculator, Spring.WcfQuickStart.ClientApp"
factory-object="webCalculatorChannelFactory"
factory-object="serverWebCalculatorChannelFactory"
factory-method="CreateChannel" />
<object id="webCalculatorChannelFactory"
<object id="serverWebCalculatorChannelFactory"
type="System.ServiceModel.ChannelFactory&lt;Spring.WcfQuickStart.ICalculator>, System.ServiceModel">
<constructor-arg name="endpointConfigurationName" value="webCalculatorEndpoint" />
<constructor-arg name="endpointConfigurationName" value="serverWebCalculatorEndpoint" />
</object>
</objects>

View File

@@ -72,7 +72,6 @@
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<EmbeddedResource Include="Config\Web.xml" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Config\ServerApp.xml" />
@@ -94,6 +93,9 @@
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Config\ServerWeb.xml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -14,7 +14,7 @@
<OldToolsVersion>2.0</OldToolsVersion>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v3.0</TargetFrameworkVersion>
<PublishUrl>http://localhost/Spring.WcfQuickStart.ServerApp/</PublishUrl>
<Install>true</Install>
<InstallFrom>Web</InstallFrom>
@@ -62,9 +62,6 @@
<HintPath>..\..\..\..\..\bin\net\3.0\debug\Spring.Services.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL" />
<Reference Include="System.Xml" />

View File

@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Spring.WcfQuickStart.ServerWeb")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Spring.WcfQuickStart.ServerWeb")]
[assembly: AssemblyCopyright("Copyright © 2008")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("3d5900ae-111a-45be-96b3-d9e4606ca793")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,88 @@
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{EEC5B531-104B-44E6-975B-44C0C8973405}</ProjectGuid>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Spring.WcfQuickStart</RootNamespace>
<AssemblyName>Spring.WcfQuickStart.ServerWeb</AssemblyName>
<TargetFrameworkVersion>v3.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Spring.Core, Version=1.2.0.20313, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\bin\net\2.0\debug\Spring.Core.dll</HintPath>
</Reference>
<Reference Include="Spring.Services, Version=1.2.0.30313, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\bin\net\3.0\debug\Spring.Services.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.ServiceModel">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Xml" />
<Reference Include="System.Configuration" />
<Reference Include="System.Web.Services" />
<Reference Include="System.EnterpriseServices" />
<Reference Include="System.Web.Mobile" />
</ItemGroup>
<ItemGroup>
<Content Include="Web.config" />
</ItemGroup>
<ItemGroup>
<Compile Include="CalculatorService.cs" />
<Compile Include="ICalculator.cs" />
<Content Include="Calculator.svc" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>False</UseIIS>
<AutoAssignPort>False</AutoAssignPort>
<DevelopmentServerPort>2637</DevelopmentServerPort>
<DevelopmentServerVPath>/Spring.WcfQuickStart.ServerWeb/</DevelopmentServerVPath>
<IISUrl>
</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@@ -0,0 +1,75 @@
<configuration>
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>
</sectionGroup>
</configSections>
<spring>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net">
<!-- Service definition -->
<object id="calculator" type="Spring.WcfQuickStart.CalculatorService, Spring.WcfQuickStart.ServerWeb"
singleton="false">
<property name="SleepInSeconds" value="1"/>
</object>
</objects>
</spring>
<system.serviceModel>
<services>
<service name="calculator" behaviorConfiguration="DefaultBehavior">
<endpoint address="" binding="basicHttpBinding" contract="Spring.WcfQuickStart.ICalculator"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DefaultBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<appSettings/>
<connectionStrings/>
<system.web>
<!--
Set compilation debug="true" to insert debugging
symbols into the compiled page. Because this
affects performance, set this value to true only
during development.
-->
<compilation debug="true">
</compilation>
<!--
The <authentication> section enables configuration
of the security authentication mode used by
ASP.NET to identify an incoming user.
-->
<authentication mode="Windows"/>
<!--
The <customErrors> section enables configuration
of what to do if/when an unhandled error occurs
during the execution of a request. Specifically,
it enables developers to configure html error pages
to be displayed in place of a error stack trace.
<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
<error statusCode="403" redirect="NoAccess.htm" />
<error statusCode="404" redirect="FileNotFound.htm" />
</customErrors>
-->
</system.web>
</configuration>

View File

@@ -1,134 +0,0 @@
<?xml version="1.0"?>
<!--
Note: As an alternative to hand editing this file you can use the
web admin tool to configure settings for your application. Use
the Website->Asp.Net Configuration option in Visual Studio.
A full list of settings and comments can be found in
machine.config.comments usually located in
\Windows\Microsoft.Net\Framework\v2.x\Config
-->
<configuration>
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>
</sectionGroup>
<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
<sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere"/>
<section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
<section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
<section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/></sectionGroup></sectionGroup></sectionGroup></configSections>
<spring>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net">
<!-- Service definition -->
<object id="calculator" type="Spring.WcfQuickStart.CalculatorService, App_Code" singleton="false">
<property name="SleepInSeconds" value="1"/>
</object>
</objects>
</spring>
<system.serviceModel>
<services>
<service name="calculator" behaviorConfiguration="DefaultBehavior">
<endpoint address="" binding="basicHttpBinding" contract="Spring.WcfQuickStart.ICalculator"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DefaultBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<appSettings/>
<connectionStrings/>
<system.web>
<!--
Set compilation debug="true" to insert debugging
symbols into the compiled page. Because this
affects performance, set this value to true only
during development.
-->
<compilation debug="true">
<assemblies>
<add assembly="System.Security, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="Microsoft.Transactions.Bridge, Version=3.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="SMDiagnostics, Version=3.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.IdentityModel.Selectors, Version=3.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Messaging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.DirectoryServices, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.Transactions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Web.RegularExpressions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.ServiceProcess, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/></assemblies>
</compilation>
<!--
The <authentication> section enables configuration
of the security authentication mode used by
ASP.NET to identify an incoming user.
-->
<authentication mode="Windows"/>
<!--
The <customErrors> section enables configuration
of what to do if/when an unhandled error occurs
during the execution of a request. Specifically,
it enables developers to configure html error pages
to be displayed in place of a error stack trace.
<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
<error statusCode="403" redirect="NoAccess.htm" />
<error statusCode="404" redirect="FileNotFound.htm" />
</customErrors>
-->
<pages>
<controls>
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/></controls></pages>
<httpHandlers>
<remove verb="*" path="*.asmx"/>
<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add verb="GET,HEAD" path="ScriptResource.axd" validate="false" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/></httpHandlers>
<httpModules>
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/></httpModules></system.web>
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CSharp.CSharpCodeProvider,System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" warningLevel="4">
<providerOption name="CompilerVersion" value="v3.5"/>
<providerOption name="WarnAsError" value="false"/></compiler>
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" warningLevel="4">
<providerOption name="CompilerVersion" value="v3.5"/>
<providerOption name="OptionInfer" value="true"/>
<providerOption name="WarnAsError" value="false"/></compiler></compilers></system.codedom>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules>
<remove name="ScriptModule"/>
<add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/></modules>
<handlers>
<remove name="WebServiceHandlerFactory-Integrated"/>
<remove name="ScriptHandlerFactory"/>
<remove name="ScriptHandlerFactoryAppServices"/>
<remove name="ScriptResource"/>
<add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add name="ScriptResource" verb="GET,HEAD" path="ScriptResource.axd" preCondition="integratedMode" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/></handlers></system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/></dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/></dependentAssembly></assemblyBinding></runtime></configuration>

View File

@@ -23,7 +23,7 @@
using System;
using System.ServiceModel;
using Spring.Context;
using Spring.Objects.Factory;
#endregion
@@ -35,8 +35,7 @@ namespace Spring.ServiceModel.Activation
/// to host objects created with Spring's IoC container.
/// </summary>
/// <author>Bruno Baia</author>
/// <version>$Id: ServiceHostFactory.cs,v 1.2 2007/05/18 21:04:37 bbaia Exp $</version>
public class ServiceHostFactoryObject : IFactoryObject, IApplicationContextAware, IInitializingObject, IDisposable
public class ServiceHostFactoryObject : IFactoryObject, IInitializingObject, IObjectFactoryAware, IDisposable
{
#region Logging
@@ -48,7 +47,11 @@ namespace Spring.ServiceModel.Activation
private string _targetName;
private Uri[] _baseAddresses = new Uri[] { };
private IApplicationContext _applicationContext;
/// <summary>
/// The owning factory.
/// </summary>
protected IObjectFactory objectFactory;
/// <summary>
/// The <see cref="Spring.ServiceModel.SpringServiceHost" /> instance managed by this factory.
@@ -97,38 +100,30 @@ namespace Spring.ServiceModel.Activation
#endregion
#region IApplicationContextAware Members
#region IObjectFactoryAware Members
/// <summary>
/// Sets the <see cref="Spring.Context.IApplicationContext"/> that this
/// object runs in.
/// Callback that supplies the owning factory to an object instance.
/// </summary>
/// <value></value>
/// <value>
/// Owning <see cref="Spring.Objects.Factory.IObjectFactory"/>
/// (may not be <see langword="null"/>). The object can immediately
/// call methods on the factory.
/// </value>
/// <remarks>
/// <p>
/// Normally this call will be used to initialize the object.
/// </p>
/// <p>
/// Invoked after population of normal object properties but before an
/// init callback such as
/// <see cref="Spring.Objects.Factory.IInitializingObject"/>'s
/// Invoked after population of normal object properties but before an init
/// callback like <see cref="Spring.Objects.Factory.IInitializingObject"/>'s
/// <see cref="Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
/// or a custom init-method. Invoked after the setting of any
/// <see cref="Spring.Context.IResourceLoaderAware"/>'s
/// <see cref="Spring.Context.IResourceLoaderAware.ResourceLoader"/>
/// property.
/// method or a custom init-method.
/// </p>
/// </remarks>
/// <exception cref="Spring.Context.ApplicationContextException">
/// In the case of application context initialization errors.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// If thrown by any application context methods.
/// In case of initialization errors.
/// </exception>
/// <exception cref="Spring.Objects.Factory.ObjectInitializationException"/>
public IApplicationContext ApplicationContext
public virtual IObjectFactory ObjectFactory
{
set { _applicationContext = value; }
set { this.objectFactory = value; }
}
#endregion
@@ -170,13 +165,13 @@ namespace Spring.ServiceModel.Activation
#region IInitializingObject Members
/// <summary>
/// Publish the object
/// Publish the object.
/// </summary>
public void AfterPropertiesSet()
public virtual void AfterPropertiesSet()
{
ValidateConfiguration();
springServiceHost = new SpringServiceHost(TargetName, _applicationContext, BaseAddresses);
springServiceHost = new SpringServiceHost(TargetName, objectFactory, BaseAddresses);
springServiceHost.Open();
@@ -207,9 +202,12 @@ namespace Spring.ServiceModel.Activation
#endregion
#region Private Methods
#region Protected Methods
private void ValidateConfiguration()
/// <summary>
/// Validates the configuration.
/// </summary>
protected virtual void ValidateConfiguration()
{
if (TargetName == null)
{

View File

@@ -1,221 +1,493 @@
#if NET_3_0
#region License
/*
* Copyright <20> 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using System.Collections;
using Spring.Util;
using Spring.Context;
using Spring.Core.TypeResolution;
using Spring.Objects;
using Spring.Objects.Factory;
using Spring.Objects.Factory.Support;
using Spring.ServiceModel.Support;
using Spring.Context.Support;
using Spring.Proxy;
#endregion
namespace Spring.ServiceModel
{
/// <summary>
/// Registers an object type on the server as a WCF service.
/// </summary>
/// <author>Bruno Baia</author>
public class ServiceExporter : IApplicationContextAware, IObjectFactoryAware, IInitializingObject, IDisposable
{
#region Logging
private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(ServiceExporter));
#endregion
#region Fields
private string targetName;
private string[] _contracts;
private IList _typeAttributes = new ArrayList();
private IDictionary _memberAttributes = new Hashtable();
private IApplicationContext applicationContext;
private AbstractObjectFactory objectFactory;
private System.ServiceModel.ServiceHost serviceHost;
#endregion
#region Constructor(s) / Destructor
/// <summary>
/// Creates a new instance of the <see cref="ServiceExporter"/> class.
/// </summary>
public ServiceExporter()
{
}
#endregion
#region Properties
/// <summary>
/// Gets or sets the name of the target object definition.
/// </summary>
public string TargetName
{
get { return targetName; }
set { targetName = value; }
}
/// <summary>
/// Gets or sets the list of service contracts.
/// </summary>
/// <remarks>
/// If not set, all the interfaces implemented or inherited
/// by the target type will be used.
/// </remarks>
/// <value>The interfaces.</value>
public string[] Contracts
{
get { return _contracts; }
set { _contracts = value; }
}
/// <summary>
/// Gets or sets a list of custom attributes
/// that should be applied to the WCF service class.
/// </summary>
public IList TypeAttributes
{
get { return _typeAttributes; }
set { _typeAttributes = value; }
}
/// <summary>
/// Gets or sets a dictionary of custom attributes
/// that should be applied to the WCF service members.
/// </summary>
/// <remarks>
/// Dictionary key is an expression that members can be matched against.
/// Value is a list of attributes that should be applied
/// to each member that matches expression.
/// </remarks>
public IDictionary MemberAttributes
{
get { return _memberAttributes; }
set { _memberAttributes = value; }
}
#endregion
#region IApplicationContextAware Members
/// <summary>
/// Gets or sets the <see cref="Spring.Context.IApplicationContext"/> that this
/// object runs in.
/// </summary>
public IApplicationContext ApplicationContext
{
get { return applicationContext; }
set { applicationContext = value; }
}
#endregion
#region IObjectFactoryAware Members
/// <summary>
/// Sets object factory to use.
/// </summary>
public IObjectFactory ObjectFactory
{
set { objectFactory = (AbstractObjectFactory) value; }
}
#endregion
#region IInitializingObject Members
/// <summary>
/// Publish the object
/// </summary>
public void AfterPropertiesSet()
{
ValidateConfiguration();
Export();
}
#endregion
#region IDisposable Members
/// <summary>
/// Closes the service host.
/// </summary>
public void Dispose()
{
serviceHost.Close();
}
#endregion
#region Private Methods
private void ValidateConfiguration()
{
if (TargetName == null)
{
throw new ArgumentException("The TargetName property is required.");
}
}
private void Export()
{
string contextName = (applicationContext.Name == AbstractApplicationContext.DefaultRootContextName) ? null : applicationContext.Name;
Type targetType = objectFactory.GetType(targetName);
IProxyTypeBuilder builder = new ServiceProxyTypeBuilder(targetName, applicationContext, targetType);
if (Contracts != null && Contracts.Length > 0)
{
builder.Interfaces = TypeResolutionUtils.ResolveInterfaceArray(Contracts);
}
builder.TypeAttributes = TypeAttributes;
builder.MemberAttributes = MemberAttributes;
Type serviceType = builder.BuildProxyType();
serviceHost = new System.ServiceModel.ServiceHost(serviceType);
serviceHost.Open();
#region Instrumentation
if (LOG.IsDebugEnabled)
{
LOG.Debug(String.Format("The service '{0}' is ready and can now be accessed.", targetName));
}
#endregion
}
#endregion
}
}
#if NET_3_0
#region License
/*
* Copyright <20> 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
using System.ServiceModel;
using System.Net.Security;
using Spring.Util;
using Spring.Context;
using Spring.Core.TypeResolution;
using Spring.Objects;
using Spring.Objects.Factory;
using Spring.Objects.Factory.Support;
using Spring.Proxy;
using Spring.ServiceModel.Support;
#endregion
namespace Spring.ServiceModel
{
/// <summary>
/// Exports an object as a WCF service.
/// </summary>
/// <author>Bruno Baia</author>
public class ServiceExporter : IFactoryObject, IInitializingObject, IObjectFactoryAware, IObjectNameAware
{
#region Logging
private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(ServiceExporter));
#endregion
#region Fields
private string _targetName;
private Type _contractInterface;
private IList _typeAttributes = new ArrayList();
private IDictionary _memberAttributes = new Hashtable();
private string _name;
private string _namespace;
private string _configurationName;
private Type _callbackContract;
private ProtectionLevel _protectionLevel;
private SessionMode _sessionMode;
/// <summary>
/// The name of the object in the factory.
/// </summary>
protected string objectName;
/// <summary>
/// The owning factory.
/// </summary>
protected IObjectFactory objectFactory;
/// <summary>
/// The generated WCF service wrapper type.
/// </summary>
private Type proxyType;
#endregion
#region Constructor(s) / Destructor
/// <summary>
/// Creates a new instance of the <see cref="ServiceExporter"/> class.
/// </summary>
public ServiceExporter()
{
}
#endregion
#region Properties
/// <summary>
/// Gets or sets the name of the target object definition.
/// </summary>
public string TargetName
{
get { return _targetName; }
set { _targetName = value; }
}
/// <summary>
/// Gets or sets the service contract interface type.
/// </summary>
/// <remarks>
/// If not set, uses the unique interface implemented or inherited by the target type.
/// An error will be thrown if the target type implements more than one interface.
/// </remarks>
/// <value>The service contract interface type.</value>
public Type ContractInterface
{
get { return _contractInterface; }
set { _contractInterface = value; }
}
/// <summary>
/// Gets or sets a list of custom attributes
/// that should be applied to the WCF service class.
/// </summary>
public IList TypeAttributes
{
get { return _typeAttributes; }
set { _typeAttributes = value; }
}
/// <summary>
/// Gets or sets a dictionary of custom attributes
/// that should be applied to the WCF service members.
/// </summary>
/// <remarks>
/// Dictionary key is an expression that members can be matched against.
/// Value is a list of attributes that should be applied
/// to each member that matches expression.
/// </remarks>
public IDictionary MemberAttributes
{
get { return _memberAttributes; }
set { _memberAttributes = value; }
}
/// <summary>
/// Gets or sets the name for the &lt;portType&gt; element in
/// Web Services Description Language (WSDL).
/// </summary>
/// <value>
/// The default value is the name of the class or interface to which the
/// System.ServiceModel.ServiceContractAttribute is applied.
/// </value>
public string Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
/// Gets or sets the namespace of the &lt;portType&gt; element in
/// Web Services Description Language (WSDL).
/// </summary>
/// <value>
/// The WSDL namespace of the &lt;portType&gt; element. The default value is "http://tempuri.org".
/// </value>
public string Namespace
{
get { return _namespace; }
set { _namespace = value; }
}
/// <summary>
/// Gets or sets the name used to locate the service in an application configuration file.
/// </summary>
/// <value>
/// The name used to locate the service element in an application configuration file.
/// The default is the name of the service implementation class.
/// </value>
public string ConfigurationName
{
get { return _configurationName; }
set { _configurationName = value; }
}
/// <summary>
/// Gets or sets the type of callback contract when the contract is a duplex contract.
/// </summary>
/// <value>
/// A <see cref="System.Type"/> that indicates the callback contract. The default is null.
/// </value>
public Type CallbackContract
{
get { return _callbackContract; }
set { _callbackContract = value; }
}
/// <summary>
/// Specifies whether the binding for the contract must support the value of
/// the ProtectionLevel property.
/// </summary>
/// <value>
/// One of the <see cref="System.Net.Security.ProtectionLevel"/> values.
/// The default is <see cref="System.Net.Security.ProtectionLevel.None"/>.
/// </value>
public ProtectionLevel ProtectionLevel
{
get { return _protectionLevel; }
set { _protectionLevel = value; }
}
/// <summary>
/// Gets or sets whether sessions are allowed, not allowed or required.
/// </summary>
/// <value>
/// A <see cref="System.ServiceModel.SessionMode"/> that indicates whether sessions are allowed,
/// not allowed, or required.
/// </value>
public SessionMode SessionMode
{
get { return _sessionMode; }
set { _sessionMode = value; }
}
#endregion
#region IObjectFactoryAware Members
/// <summary>
/// Callback that supplies the owning factory to an object instance.
/// </summary>
/// <value>
/// Owning <see cref="Spring.Objects.Factory.IObjectFactory"/>
/// (may not be <see langword="null"/>). The object can immediately
/// call methods on the factory.
/// </value>
/// <remarks>
/// <p>
/// Invoked after population of normal object properties but before an init
/// callback like <see cref="Spring.Objects.Factory.IInitializingObject"/>'s
/// <see cref="Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
/// method or a custom init-method.
/// </p>
/// </remarks>
/// <exception cref="Spring.Objects.ObjectsException">
/// In case of initialization errors.
/// </exception>
public virtual IObjectFactory ObjectFactory
{
set { this.objectFactory = value; }
}
#endregion
#region IInitializingObject Members
/// <summary>
/// Publish the object
/// </summary>
public void AfterPropertiesSet()
{
ValidateConfiguration();
GenerateProxy();
}
#endregion
#region IFactoryObject Members
/// <summary>
/// Return an instance (possibly shared or independent) of the object
/// managed by this factory.
/// </summary>
/// <remarks>
/// <note type="caution">
/// If this method is being called in the context of an enclosing IoC container and
/// returns <see langword="null"/>, the IoC container will consider this factory
/// object as not being fully initialized and throw a corresponding (and most
/// probably fatal) exception.
/// </note>
/// </remarks>
/// <returns>
/// An instance (possibly shared or independent) of the object managed by
/// this factory.
/// </returns>
public object GetObject()
{
return proxyType;
}
/// <summary>
/// Return the <see cref="System.Type"/> of object that this
/// <see cref="Spring.Objects.Factory.IFactoryObject"/> creates, or
/// <see langword="null"/> if not known in advance.
/// </summary>
public Type ObjectType
{
get { return typeof(Type); }
}
/// <summary>
/// Is the object managed by this factory a singleton or a prototype?
/// </summary>
public bool IsSingleton
{
get { return false; }
}
#endregion
#region IObjectNameAware Members
/// <summary>
/// Set the name of the object in the object factory that created this object.
/// </summary>
/// <value>
/// The name of the object in the factory.
/// </value>
/// <remarks>
/// <p>
/// Invoked after population of normal object properties but before an init
/// callback like <see cref="IInitializingObject.AfterPropertiesSet"/>'s
/// <see cref="IInitializingObject"/>
/// method or a custom init-method.
/// </p>
/// </remarks>
public string ObjectName
{
set { this.objectName = value; }
}
#endregion
#region Protected Methods
/// <summary>
/// Validates the configuration.
/// </summary>
protected virtual void ValidateConfiguration()
{
if (TargetName == null)
{
throw new ArgumentException("The TargetName property is required.");
}
if (ContractInterface != null && !ContractInterface.IsInterface)
{
throw new ArgumentException("ContractInterface must be an interface.");
}
}
/// <summary>
/// Generates the WCF service wrapper type.
/// </summary>
protected virtual void GenerateProxy()
{
IProxyTypeBuilder builder = new ConfigurableServiceProxyTypeBuilder(TargetName, this.objectName, objectFactory,
Name, Namespace, ConfigurationName, CallbackContract, ProtectionLevel, SessionMode);
if (ContractInterface != null)
{
builder.Interfaces = new Type[] { ContractInterface };
}
builder.TypeAttributes = TypeAttributes;
builder.MemberAttributes = MemberAttributes;
proxyType = builder.BuildProxyType();
}
#endregion
#region ConfigurableServiceProxyTypeBuilder inner class implementation
/// <summary>
/// Builds a WCF service type.
/// </summary>
private sealed class ConfigurableServiceProxyTypeBuilder : ServiceProxyTypeBuilder
{
private CustomAttributeBuilder serviceContractAttribute;
public ConfigurableServiceProxyTypeBuilder(string targetName, string objectName, IObjectFactory objectFactory,
string name, string ns, string configurationName, Type callbackContract, ProtectionLevel protectionLevel, SessionMode sessionMode)
: base(targetName, objectName, objectFactory)
{
if (!StringUtils.HasText(configurationName))
{
name = this.Interfaces[0].Name;
configurationName = this.Interfaces[0].FullName;
}
// Creates a ServiceContractAttribute from configuration info
this.serviceContractAttribute = CreateServiceContractAttribute(name, ns, configurationName, callbackContract, protectionLevel, sessionMode);
}
private static CustomAttributeBuilder CreateServiceContractAttribute(string name, string ns, string configurationName,
Type callbackContract, ProtectionLevel protectionLevel, SessionMode sessionMode)
{
ReflectionUtils.CustomAttributeBuilderBuilder scbb =
new ReflectionUtils.CustomAttributeBuilderBuilder(typeof(ServiceContractAttribute));
if (StringUtils.HasText(name))
{
scbb.AddPropertyValue("Name", name);
}
if (StringUtils.HasText(ns))
{
scbb.AddPropertyValue("Namespace", ns);
}
if (StringUtils.HasText(configurationName))
{
scbb.AddPropertyValue("ConfigurationName", configurationName);
}
if (callbackContract != null)
{
scbb.AddPropertyValue("CallbackContract", callbackContract);
}
if (protectionLevel != ProtectionLevel.None)
{
scbb.AddPropertyValue("ProtectionLevel", protectionLevel);
}
if (sessionMode != SessionMode.Allowed)
{
scbb.AddPropertyValue("SessionMode", sessionMode);
}
return scbb.Build();
}
protected override IList GetTypeAttributes(Type type)
{
IList attrs = base.GetTypeAttributes(type);
bool containsServiceContractAttribute = false;
for (int i = 0; i < attrs.Count; i++)
{
if (IsAttributeMatchingType(attrs[i], typeof(ServiceContractAttribute)))
{
// Override existing ServiceContractAttribute
containsServiceContractAttribute = true;
attrs[i] = serviceContractAttribute;
}
}
// Add missing ServiceContractAttribute
if (!containsServiceContractAttribute)
{
attrs.Add(serviceContractAttribute);
}
return attrs;
}
protected override IList GetMethodAttributes(MethodInfo method)
{
IList attrs = base.GetMethodAttributes(method);
bool containsOperationContractAttribute = false;
foreach (object attr in attrs)
{
if (IsAttributeMatchingType(attr, typeof(OperationContractAttribute)))
{
containsOperationContractAttribute = true;
break;
}
}
// Creates default OperationContractAttribute if not set yet
if (!containsOperationContractAttribute)
{
attrs.Add(ReflectionUtils.CreateCustomAttribute(typeof(OperationContractAttribute)));
}
return attrs;
}
protected override Type[] GetProxiableInterfaces(Type[] interfaces)
{
Type[] proxiableInterfaces = base.GetProxiableInterfaces(interfaces);
if (proxiableInterfaces.Length > 1)
{
throw new ArgumentException(String.Format(
"ServiceExporter cannot export service type '{0}' as a WCF service because it implements multiple interfaces. Specify the contract interface to expose via the ContractInterface property.",
this.TargetType));
}
return proxiableInterfaces;
}
}
#endregion
}
}
#endif

View File

@@ -27,6 +27,7 @@ using Spring.Util;
using Spring.Context;
using Spring.Context.Support;
using Spring.ServiceModel.Support;
using Spring.Objects.Factory;
#endregion
@@ -65,10 +66,10 @@ namespace Spring.ServiceModel
/// Creates a new instance of the <see cref="Spring.ServiceModel.SpringServiceHost"/> class.
/// </summary>
/// <param name="serviceName">The name of the service within Spring's IoC container.</param>
/// <param name="applicationContext">The <see cref="IApplicationContext"/> to use.</param>
/// <param name="objectFactory">The <see cref="IObjectFactory"/> to use.</param>
/// <param name="baseAddresses">The base addresses for the hosted service.</param>
public SpringServiceHost(string serviceName, IApplicationContext applicationContext, params Uri[] baseAddresses)
: base(CreateServiceType(serviceName, applicationContext), baseAddresses)
public SpringServiceHost(string serviceName, IObjectFactory objectFactory, params Uri[] baseAddresses)
: base(CreateServiceType(serviceName, objectFactory), baseAddresses)
{
}
@@ -84,16 +85,21 @@ namespace Spring.ServiceModel
}
}
private static Type CreateServiceType(string serviceName, IApplicationContext applicationContext)
private static Type CreateServiceType(string serviceName, IObjectFactory objectFactory)
{
if (StringUtils.IsNullOrEmpty(serviceName))
{
throw new ArgumentException("The service name cannot be null or an empty string.", "serviceName");
}
Type serviceType = applicationContext.GetType(serviceName);
return new ServiceProxyTypeBuilder(serviceName, applicationContext, serviceType).BuildProxyType();
if (objectFactory.IsTypeMatch(serviceName, typeof(Type)))
{
return objectFactory.GetObject(serviceName) as Type;
}
else
{
return new ServiceProxyTypeBuilder(serviceName, objectFactory).BuildProxyType();
}
}
#endregion

View File

@@ -25,9 +25,8 @@ using System;
using System.Reflection;
using System.Reflection.Emit;
using Spring.Proxy;
using Spring.Context;
using Spring.Objects.Factory;
using Spring.Proxy;
#endregion
@@ -44,13 +43,13 @@ namespace Spring.ServiceModel.Support
private static readonly MethodInfo GetObject =
typeof(IObjectFactory).GetMethod("GetObject", new Type[] { typeof(string) });
private IApplicationContext applicationContext;
private string serviceName;
private IObjectFactory objectFactory;
private string targetName;
/// <summary>
/// Target instance calls should be delegated to.
/// </summary>
protected FieldBuilder applicationContextField;
protected FieldBuilder objectFactoryField;
#endregion
@@ -60,16 +59,28 @@ namespace Spring.ServiceModel.Support
/// Creates a new instance of the
/// <see cref="Spring.ServiceModel.Support.ServiceProxyTypeBuilder"/> class.
/// </summary>
/// <param name="serviceName">The name of the service within Spring's IoC container.</param>
/// <param name="applicationContext">The <see cref="IApplicationContext"/> to use.</param>
/// <param name="serviceType">The type of the service.</param>
public ServiceProxyTypeBuilder(string serviceName, IApplicationContext applicationContext, Type serviceType)
/// <param name="targetName">The name of the service within Spring's IoC container.</param>
/// <param name="objectFactory">The <see cref="IObjectFactory"/> to use.</param>
public ServiceProxyTypeBuilder(string targetName, IObjectFactory objectFactory)
: this(targetName, targetName, objectFactory)
{
this.serviceName = serviceName;
this.applicationContext = applicationContext;
}
this.Name = serviceName;
this.TargetType = serviceType;
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.ServiceModel.Support.ServiceProxyTypeBuilder"/> class.
/// </summary>
/// <param name="targetName">The name of the service within Spring's IoC container.</param>
/// <param name="serviceTypeName">The name of the generated WCF service <see cref="System.Type"/>.</param>
/// <param name="objectFactory">The <see cref="IObjectFactory"/> to use.</param>
public ServiceProxyTypeBuilder(string targetName, string serviceTypeName, IObjectFactory objectFactory)
{
this.targetName = targetName;
this.objectFactory = objectFactory;
this.Name = serviceTypeName;
this.TargetType = objectFactory.GetType(targetName);
}
#endregion
@@ -77,8 +88,8 @@ namespace Spring.ServiceModel.Support
#region Protected Methods
/// <summary>
/// Creates a proxy that delegates calls to an instance of the
/// target object. This overriden implementation also sets the field __applicationContext.
/// Creates a proxy that delegates calls to an instance of the target object.
/// This overriden implementation also sets the field __objectFactory.
/// </summary>
/// <exception cref="System.ArgumentException">
/// If the <see cref="IProxyTypeBuilder.TargetType"/>
@@ -88,8 +99,8 @@ namespace Spring.ServiceModel.Support
{
Type proxyType = base.BuildProxyType();
FieldInfo field = proxyType.GetField("__applicationContext", BindingFlags.NonPublic | BindingFlags.Static);
field.SetValue(proxyType, applicationContext);
FieldInfo field = proxyType.GetField("__objectFactory", BindingFlags.NonPublic | BindingFlags.Static);
field.SetValue(proxyType, objectFactory);
return proxyType;
}
@@ -117,8 +128,8 @@ namespace Spring.ServiceModel.Support
ILGenerator il = cb.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldsfld, applicationContextField);
il.Emit(OpCodes.Ldstr, serviceName);
il.Emit(OpCodes.Ldsfld, objectFactoryField);
il.Emit(OpCodes.Ldstr, targetName);
il.EmitCall(OpCodes.Callvirt, GetObject, null);
il.Emit(OpCodes.Stfld, targetInstance);
@@ -135,7 +146,7 @@ namespace Spring.ServiceModel.Support
{
TypeBuilder typeBuilder = DynamicProxyManager.CreateTypeBuilder(name, baseType);
applicationContextField = typeBuilder.DefineField("__applicationContext", typeof(IApplicationContext),
objectFactoryField = typeBuilder.DefineField("__objectFactory", typeof(IObjectFactory),
FieldAttributes.Private | FieldAttributes.Static | FieldAttributes.InitOnly);
return typeBuilder;

View File

@@ -22,10 +22,17 @@
#region Imports
using System;
using System.IO;
using System.Text;
using System.Reflection;
using System.Net.Security;
using System.ServiceModel;
using NUnit.Framework;
using Spring.ServiceModel;
using Spring.Core.IO;
using Spring.Objects.Factory;
using Spring.Objects.Factory.Xml;
#endregion
@@ -35,47 +42,10 @@ namespace Spring.ServiceModel
/// Unit tests for the ServiceExporter class.
/// </summary>
/// <author>Bruno Baia</author>
/// <version>$Id: ServiceExporterTests.cs,v 1.1 2007/09/21 14:27:35 bbaia Exp $</version>
[TestFixture]
public sealed class ServiceExporterTests
{
#region Test classes
public interface IService
{
string SomeMethod(int param);
}
[ServiceContract(Namespace = "http://Spring.Services.Tests")]
public interface IDecoratedService
{
[OperationContract]
string SomeMethod(int param);
}
public class Service : IDecoratedService
{
public string SomeMethod(int param)
{
return param.ToString();
}
}
[ServiceContract(Namespace = "http://Spring.Services.Tests")]
public class DecoratedService : IService
{
[OperationContract]
public string SomeMethod(int param)
{
return param.ToString();
}
}
#endregion
/*
WebServiceExporter wse = null;
ServiceExporter se = null;
[SetUp]
public void SetUp()
@@ -83,177 +53,185 @@ namespace Spring.ServiceModel
const string xml =
@"<?xml version='1.0' encoding='UTF-8' ?>
<objects xmlns='http://www.springframework.net'>
<object id='noDecoratedService' type='Spring.Web.Services.WebServiceExporterTests+NoDecoratedService, Spring.Web.Tests'/>
<object id='decoratedService' type='Spring.Web.Services.WebServiceExporterTests+DecoratedService, Spring.Web.Tests'/>
<object id='service' type='Spring.ServiceModel.ServiceExporterTests+Service, Spring.Services.Tests'/>
<object id='decoratedService' type='Spring.ServiceModel.ServiceExporterTests+DecoratedService, Spring.Services.Tests'/>
</objects>";
Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(xml));
IObjectFactory objectFactory = new XmlObjectFactory(new InputStreamResource(stream, string.Empty));
wse = new WebServiceExporter();
wse.ObjectFactory = objectFactory;
se = new ServiceExporter();
se.ObjectFactory = objectFactory;
}
[Test]
[ExpectedException(typeof(ArgumentException), "The TargetName property is required.")]
[ExpectedException(typeof(ArgumentException), ExpectedMessage = "The TargetName property is required.")]
public void NullConfig()
{
wse.ObjectName = "NullConfig";
wse.AfterPropertiesSet();
se.ObjectName = "NullConfig";
se.AfterPropertiesSet();
}
[Test]
public void ProxiesTargetInterfaces()
public void ProxiesContractInterface()
{
wse.ObjectName = "ProxiesTargetInterfaces";
wse.TargetName = "noDecoratedService";
wse.AfterPropertiesSet();
se.ObjectName = "ProxiesContractInterface";
se.TargetName = "service";
se.AfterPropertiesSet();
Type proxyType = wse.ObjectType;
Assert.IsTrue(typeof(IService).IsAssignableFrom(proxyType));
Type proxyType = se.GetObject() as Type;
Assert.IsNotNull(proxyType);
Assert.IsTrue(typeof(IContract).IsAssignableFrom(proxyType));
}
[Test]
public void CreatesWebServiceAttributeWithNoDecoratedClassAndMinimalConfig()
public void ProxyTypeEqualsObjectName()
{
wse.ObjectName = "CreatesWebServiceAttributeWithNoDecoratedClassAndMinimalConfig";
wse.TargetName = "noDecoratedService";
wse.AfterPropertiesSet();
se.ObjectName = "ProxyTypeEqualsObjectName";
se.TargetName = "service";
se.AfterPropertiesSet();
Type proxyType = wse.ObjectType;
object[] attrs = proxyType.GetCustomAttributes(typeof(WebServiceAttribute), true);
Type proxyType = se.GetObject() as Type;
Assert.IsNotNull(proxyType);
Assert.AreEqual("ProxyTypeEqualsObjectName", proxyType.FullName);
}
[Test]
public void CreatesServiceContractAttributeWithNoDecoratedClassAndMinimalConfig()
{
se.ObjectName = "CreatesServiceContractAttributeWithNoDecoratedClassAndMinimalConfig";
se.TargetName = "service";
se.AfterPropertiesSet();
Type proxyType = se.GetObject() as Type;
Assert.IsNotNull(proxyType);
object[] attrs = proxyType.GetCustomAttributes(typeof(ServiceContractAttribute), true);
Assert.IsNotEmpty(attrs);
Assert.AreEqual(1, attrs.Length);
WebServiceAttribute wsa = attrs[0] as WebServiceAttribute;
Assert.AreEqual("CreatesWebServiceAttributeWithNoDecoratedClassAndMinimalConfig", wsa.Name);
Assert.AreEqual(string.Empty, wsa.Description);
Assert.AreEqual(WebServiceAttribute.DefaultNamespace, wsa.Namespace);
ServiceContractAttribute sca = attrs[0] as ServiceContractAttribute;
Assert.IsNull(sca.CallbackContract);
Assert.AreEqual(typeof(IContract).FullName, sca.ConfigurationName);
Assert.AreEqual(typeof(IContract).Name, sca.Name);
Assert.IsNull(sca.Namespace);
Assert.AreEqual(ProtectionLevel.None, sca.ProtectionLevel);
Assert.AreEqual(SessionMode.Allowed, sca.SessionMode);
}
[Test]
public void CreatesWebServiceAttributeWithNoDecoratedClassAndFullConfig()
public void CreatesServiceContractAttributeWithNoDecoratedClassAndFullConfig()
{
wse.ObjectName = "CreatesWebServiceAttributeWithNoDecoratedClassAndFullConfig";
wse.TargetName = "noDecoratedService";
wse.Name = "My web service name";
wse.Description = "My web service description";
wse.Namespace = "http://www.springframework.net";
wse.AfterPropertiesSet();
se.ObjectName = "CreatesServiceContractAttributeWithNoDecoratedClassAndFullConfig";
se.TargetName = "service";
se.CallbackContract = typeof(IDisposable);
se.ConfigurationName = "CustomConfigName";
se.Name = "serviceName";
se.Namespace = "http://Spring.Services.Tests";
se.ProtectionLevel = ProtectionLevel.Sign;
se.SessionMode = SessionMode.Required;
se.AfterPropertiesSet();
Type proxyType = wse.ObjectType;
object[] attrs = proxyType.GetCustomAttributes(typeof(WebServiceAttribute), true);
Type proxyType = se.GetObject() as Type;
Assert.IsNotNull(proxyType);
object[] attrs = proxyType.GetCustomAttributes(typeof(ServiceContractAttribute), true);
Assert.IsNotEmpty(attrs);
Assert.AreEqual(1, attrs.Length);
WebServiceAttribute wsa = attrs[0] as WebServiceAttribute;
Assert.AreEqual(wse.Name, wsa.Name);
Assert.AreEqual(wse.Description, wsa.Description);
Assert.AreEqual(wse.Namespace, wsa.Namespace);
ServiceContractAttribute sca = attrs[0] as ServiceContractAttribute;
Assert.AreEqual(se.CallbackContract, sca.CallbackContract);
Assert.AreEqual(se.ConfigurationName, sca.ConfigurationName);
Assert.AreEqual(se.Name, sca.Name);
Assert.AreEqual(se.Namespace, sca.Namespace);
Assert.AreEqual(se.ProtectionLevel, sca.ProtectionLevel);
Assert.AreEqual(se.SessionMode, sca.SessionMode);
}
[Test]
public void CreatesDefaultWebMethodAttributeWithNoDecoratedMethod()
public void CreatesDefaultOperationContractAttributeWithNoDecoratedMethod()
{
wse.ObjectName = "CreatesDefaultWebMethodAttributeWithNoDecoratedMethod";
wse.TargetName = "noDecoratedService";
wse.AfterPropertiesSet();
se.ObjectName = "CreatesDefaultOperationContractAttributeWithNoDecoratedMethod";
se.TargetName = "service";
se.AfterPropertiesSet();
Type proxyType = wse.ObjectType;
Type proxyType = se.GetObject() as Type;
Assert.IsNotNull(proxyType);
MethodInfo method = proxyType.GetMethod("SomeMethod");
Assert.IsNotNull(method);
object[] attrs = method.GetCustomAttributes(typeof(WebMethodAttribute), true);
object[] attrs = method.GetCustomAttributes(typeof(OperationContractAttribute), true);
Assert.IsNotEmpty(attrs);
Assert.AreEqual(1, attrs.Length);
}
[Test]
public void CreatesCustomWebMethodAttributeWithNoDecoratedMethod()
public void CreatesCustomOperationContractAttributeWithNoDecoratedMethod()
{
wse.ObjectName = "CreatesCustomWebMethodAttributeWithNoDecoratedMethod";
wse.TargetName = "noDecoratedService";
wse.MemberAttributes.Add("SomeMethod", new WebMethodAttribute(true)); // default value is false
wse.AfterPropertiesSet();
OperationContractAttribute oca1 = new OperationContractAttribute();
oca1.Name = "MySomeMethod";
Type proxyType = wse.ObjectType;
se.ObjectName = "CreatesCustomOperationContractAttributeWithNoDecoratedMethod";
se.TargetName = "service";
se.MemberAttributes.Add("SomeMethod", oca1);
se.AfterPropertiesSet();
Type proxyType = se.GetObject() as Type;
Assert.IsNotNull(proxyType);
MethodInfo method = proxyType.GetMethod("SomeMethod");
Assert.IsNotNull(method);
object[] attrs = method.GetCustomAttributes(typeof(WebMethodAttribute), true);
object[] attrs = method.GetCustomAttributes(typeof(OperationContractAttribute), true);
Assert.IsNotEmpty(attrs);
Assert.AreEqual(1, attrs.Length);
WebMethodAttribute wma = attrs[0] as WebMethodAttribute;
Assert.AreEqual(true, wma.EnableSession);
OperationContractAttribute oca2 = attrs[0] as OperationContractAttribute;
Assert.AreEqual(oca1.Name, oca2.Name);
}
[Test]
public void OverridesExistingWebServiceAttributeWithDecoratedClass()
public void OverridesExistingServiceContractAttributeWithDecoratedClass()
{
wse.ObjectName = "OverridesExistingWebServiceAttributeWithDecoratedClass";
wse.TargetName = "decoratedService";
wse.AfterPropertiesSet();
se.ObjectName = "OverridesExistingServiceContractAttributeWithDecoratedClass";
se.TargetName = "decoratedService";
se.AfterPropertiesSet();
Type proxyType = wse.ObjectType;
object[] attrs = proxyType.GetCustomAttributes(typeof(WebServiceAttribute), true);
Type proxyType = se.GetObject() as Type;
Assert.IsNotNull(proxyType);
object[] attrs = proxyType.GetCustomAttributes(typeof(ServiceContractAttribute), true);
Assert.IsNotEmpty(attrs);
Assert.AreEqual(1, attrs.Length);
WebServiceAttribute wsa = attrs[0] as WebServiceAttribute;
Assert.AreEqual("OverridesExistingWebServiceAttributeWithDecoratedClass", wsa.Name);
Assert.AreEqual(string.Empty, wsa.Description);
Assert.AreEqual(WebServiceAttribute.DefaultNamespace, wsa.Namespace);
ServiceContractAttribute sca = attrs[0] as ServiceContractAttribute;
Assert.IsNull(sca.Namespace);
}
[Test]
public void UsesExistingWebMethodAttributeWithDecoratedMethod()
public void UsesExistingOperationContractAttributeWithDecoratedMethod()
{
wse.ObjectName = "UsesExistingWebMethodAttributeWithDecoratedMethod";
wse.TargetName = "decoratedService";
wse.AfterPropertiesSet();
se.ObjectName = "UsesExistingOperationContractAttributeWithDecoratedMethod";
se.TargetName = "decoratedService";
se.AfterPropertiesSet();
Type proxyType = wse.ObjectType;
Type proxyType = se.GetObject() as Type;
Assert.IsNotNull(proxyType);
MethodInfo method = proxyType.GetMethod("SomeMethod");
Assert.IsNotNull(method);
object[] attrs = method.GetCustomAttributes(typeof(WebMethodAttribute), true);
object[] attrs = method.GetCustomAttributes(typeof(OperationContractAttribute), true);
Assert.IsNotEmpty(attrs);
Assert.AreEqual(1, attrs.Length);
WebMethodAttribute wma = attrs[0] as WebMethodAttribute;
Assert.AreEqual("SomeMethod description", wma.Description);
}
// TODO : attributes override
[Test]
[Ignore("Attributes override not implemented.")]
public void OverridesExistingWebMethodAttributeWithDecoratedMethod()
{
wse.ObjectName = "OverridesExistingWebMethodAttributeWithDecoratedMethod";
wse.TargetName = "decoratedService";
wse.MemberAttributes.Add("SomeMethod", new WebMethodAttribute(true)); // default value is false
wse.AfterPropertiesSet();
Type proxyType = wse.ObjectType;
MethodInfo method = proxyType.GetMethod("SomeMethod");
Assert.IsNotNull(method);
object[] attrs = method.GetCustomAttributes(typeof(WebMethodAttribute), true);
Assert.IsNotEmpty(attrs);
Assert.AreEqual(1, attrs.Length);
WebMethodAttribute wma = attrs[0] as WebMethodAttribute;
Assert.AreEqual(true, wma.EnableSession);
OperationContractAttribute oca = attrs[0] as OperationContractAttribute;
Assert.AreEqual("MySomeMethod", oca.Name);
}
#region Test classes
public interface IService
public interface IContract
{
string SomeMethod(int param);
}
public class NoDecoratedService : IService
public class Service : IContract
{
public string SomeMethod(int param)
{
@@ -261,18 +239,33 @@ namespace Spring.ServiceModel
}
}
[WebService(Name = "Decorated service")]
public class DecoratedService : IService
[ServiceContract(Namespace = "http://Spring.Services.Tests")]
public class DecoratedService : IContract
{
[WebMethod(Description="SomeMethod description")]
[OperationContract(Name = "MySomeMethod")]
public string SomeMethod(int param)
{
return param.ToString();
}
}
//[ServiceContract(Namespace = "http://Spring.Services.Tests")]
//public interface IDecoratedContract
//{
// [OperationContract]
// string SomeMethod(int param);
//}
//public class AnotherService : IDecoratedContract
//{
// public string SomeMethod(int param)
// {
// return param.ToString();
// }
//}
#endregion
*/
}
}
#endif