diff --git a/Microsoft.Extensions.AspNet.sln b/Microsoft.Extensions.AspNet.sln index 9718403..3e1d14e 100644 --- a/Microsoft.Extensions.AspNet.sln +++ b/Microsoft.Extensions.AspNet.sln @@ -52,10 +52,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".info", ".info", "{BE18BA32 README.md = README.md EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Extensions.Configuration.ConfigurationManager", "src\Microsoft.Extensions.Configuration.ConfigurationManager\Microsoft.Extensions.Configuration.ConfigurationManager.csproj", "{EB4BBFE9-108E-48C4-AF64-2806CD96E06D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Configuration.ConfigurationManager", "src\Microsoft.Extensions.Configuration.ConfigurationManager\Microsoft.Extensions.Configuration.ConfigurationManager.csproj", "{EB4BBFE9-108E-48C4-AF64-2806CD96E06D}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Configuration.ConfigurationManager.Tests", "tests\Microsoft.Extensions.Configuration.ConfigurationManager.Tests\Microsoft.Extensions.Configuration.ConfigurationManager.Tests.csproj", "{D6BB544A-7A32-4C2B-A5BA-3DC6A5C0CA5E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Extensions.ServiceModel", "src\Microsoft.Extensions.ServiceModel\Microsoft.Extensions.ServiceModel.csproj", "{DDF80027-4AFA-45F2-BE32-2EDA81B620FD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -198,6 +200,18 @@ Global {D6BB544A-7A32-4C2B-A5BA-3DC6A5C0CA5E}.Release|x64.Build.0 = Release|Any CPU {D6BB544A-7A32-4C2B-A5BA-3DC6A5C0CA5E}.Release|x86.ActiveCfg = Release|Any CPU {D6BB544A-7A32-4C2B-A5BA-3DC6A5C0CA5E}.Release|x86.Build.0 = Release|Any CPU + {DDF80027-4AFA-45F2-BE32-2EDA81B620FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DDF80027-4AFA-45F2-BE32-2EDA81B620FD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DDF80027-4AFA-45F2-BE32-2EDA81B620FD}.Debug|x64.ActiveCfg = Debug|Any CPU + {DDF80027-4AFA-45F2-BE32-2EDA81B620FD}.Debug|x64.Build.0 = Debug|Any CPU + {DDF80027-4AFA-45F2-BE32-2EDA81B620FD}.Debug|x86.ActiveCfg = Debug|Any CPU + {DDF80027-4AFA-45F2-BE32-2EDA81B620FD}.Debug|x86.Build.0 = Debug|Any CPU + {DDF80027-4AFA-45F2-BE32-2EDA81B620FD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DDF80027-4AFA-45F2-BE32-2EDA81B620FD}.Release|Any CPU.Build.0 = Release|Any CPU + {DDF80027-4AFA-45F2-BE32-2EDA81B620FD}.Release|x64.ActiveCfg = Release|Any CPU + {DDF80027-4AFA-45F2-BE32-2EDA81B620FD}.Release|x64.Build.0 = Release|Any CPU + {DDF80027-4AFA-45F2-BE32-2EDA81B620FD}.Release|x86.ActiveCfg = Release|Any CPU + {DDF80027-4AFA-45F2-BE32-2EDA81B620FD}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -215,6 +229,7 @@ Global {F29821A2-9312-4ABF-AC2C-D06D3AF67919} = {A4274275-5F57-4EC3-9651-AD4BCFB0E488} {EB4BBFE9-108E-48C4-AF64-2806CD96E06D} = {2355A742-ABD4-402A-8040-A46B7D88BAB5} {D6BB544A-7A32-4C2B-A5BA-3DC6A5C0CA5E} = {85C121D2-EBA5-4580-A375-4383371885A0} + {DDF80027-4AFA-45F2-BE32-2EDA81B620FD} = {2355A742-ABD4-402A-8040-A46B7D88BAB5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {20512F05-6FBC-47B7-BBE8-949744341E3D} diff --git a/demo/SampleWebApplication/SampleWebApplication.csproj b/demo/SampleWebApplication/SampleWebApplication.csproj index 5fbe249..df831c8 100644 --- a/demo/SampleWebApplication/SampleWebApplication.csproj +++ b/demo/SampleWebApplication/SampleWebApplication.csproj @@ -25,6 +25,7 @@ 4.3 + True true @@ -214,6 +215,7 @@ True True + ..\..\packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net463\System.Security.Cryptography.Algorithms.dll True @@ -229,6 +231,7 @@ True True + ..\..\packages\System.Text.Encodings.Web.5.0.1\lib\net461\System.Text.Encodings.Web.dll @@ -317,7 +320,8 @@ - + + @@ -356,7 +360,11 @@ - + + Feed.svc + + + Feed.ashx @@ -439,6 +447,10 @@ {eb4bbfe9-108e-48c4-af64-2806cd96e06d} Microsoft.Extensions.Configuration.ConfigurationManager + + {ddf80027-4afa-45f2-be32-2eda81b620fd} + Microsoft.Extensions.ServiceModel + 10.0 @@ -456,7 +468,7 @@ True 1267 / - https://localhost:44373/ + https://localhost:44383/ False False diff --git a/demo/SampleWebApplication/ServiceModel/Feed.svc b/demo/SampleWebApplication/ServiceModel/Feed.svc new file mode 100644 index 0000000..8766100 --- /dev/null +++ b/demo/SampleWebApplication/ServiceModel/Feed.svc @@ -0,0 +1 @@ +<%@ ServiceHost Language="C#" Debug="true" Service="SampleWebApplication.ServiceModel.Feed" CodeBehind="Feed.svc.cs" %> diff --git a/demo/SampleWebApplication/ServiceModel/Feed.svc.cs b/demo/SampleWebApplication/ServiceModel/Feed.svc.cs new file mode 100644 index 0000000..5e7f485 --- /dev/null +++ b/demo/SampleWebApplication/ServiceModel/Feed.svc.cs @@ -0,0 +1,31 @@ +using System; +using System.ServiceModel; +using System.ServiceModel.Syndication; +using System.Threading.Tasks; +using Microsoft.Extensions.Options; +using Microsoft.Extensions.ServiceModel.DependencyInjection; +using SampleWebApplication.Options; +using SampleWebApplication.Services; + +namespace SampleWebApplication.ServiceModel +{ + [SystemWebHostServiceBehavior()] + public class Feed : IFeed + { + private readonly ISyndicationClient syndicationClient; + private readonly FeedOptions options; + + public Feed(ISyndicationClient syndicationClient, IOptions options) + { + this.syndicationClient = syndicationClient ?? throw new ArgumentNullException(nameof(syndicationClient)); + this.options = options?.Value ?? throw new ArgumentNullException(nameof(options)); + } + + public async Task GetFeedAsync() + { + var feed = await syndicationClient.GetSyndicationFeedAsync(options.Uri); + + return feed.Title.Text; + } + } +} diff --git a/demo/SampleWebApplication/ServiceModel/IFeed.cs b/demo/SampleWebApplication/ServiceModel/IFeed.cs new file mode 100644 index 0000000..9073a1f --- /dev/null +++ b/demo/SampleWebApplication/ServiceModel/IFeed.cs @@ -0,0 +1,14 @@ +using System.ServiceModel; +using System.ServiceModel.Syndication; +using System.Threading.Tasks; + +namespace SampleWebApplication.ServiceModel +{ + // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IFeed" in both code and config file together. + [ServiceContract] + public interface IFeed + { + [OperationContract(Action = "GetFeed")] + Task GetFeedAsync(); + } +} diff --git a/demo/SampleWebApplication/Site.Master b/demo/SampleWebApplication/Site.Master index 64d50a6..e5ceb6d 100644 --- a/demo/SampleWebApplication/Site.Master +++ b/demo/SampleWebApplication/Site.Master @@ -53,7 +53,7 @@
  • MVC
  • Web Forms
  • Web API
  • -
  • Web Handler
  • +
  • Web Handler
  • diff --git a/demo/SampleWebApplication/Views/Shared/_Layout.cshtml b/demo/SampleWebApplication/Views/Shared/_Layout.cshtml index 76905db..db9bf89 100644 --- a/demo/SampleWebApplication/Views/Shared/_Layout.cshtml +++ b/demo/SampleWebApplication/Views/Shared/_Layout.cshtml @@ -23,7 +23,7 @@
  • @Html.ActionLink("MVC", "Index", "Home")
  • Web Forms
  • Web API
  • -
  • Web Handler
  • +
  • Web Handler
  • diff --git a/demo/SampleWebApplication/Web.config b/demo/SampleWebApplication/Web.config index e41a82c..2b49796 100644 --- a/demo/SampleWebApplication/Web.config +++ b/demo/SampleWebApplication/Web.config @@ -1,4 +1,4 @@ - + + + + + + + + + + + + diff --git a/demo/SampleWebApplication/WebServices/Feed.ashx b/demo/SampleWebApplication/WebHandlers/Feed.ashx similarity index 56% rename from demo/SampleWebApplication/WebServices/Feed.ashx rename to demo/SampleWebApplication/WebHandlers/Feed.ashx index 6d02100..4bc399a 100644 --- a/demo/SampleWebApplication/WebServices/Feed.ashx +++ b/demo/SampleWebApplication/WebHandlers/Feed.ashx @@ -1 +1 @@ -<%@ WebHandler Language="C#" CodeBehind="Feed.ashx.cs" Class="SampleWebApplication.WebServices.FeedHandler" %> +<%@ WebHandler Language="C#" CodeBehind="Feed.ashx.cs" Class="SampleWebApplication.WebHandlers.FeedHandler" %> diff --git a/demo/SampleWebApplication/WebServices/Feed.ashx.cs b/demo/SampleWebApplication/WebHandlers/Feed.ashx.cs similarity index 89% rename from demo/SampleWebApplication/WebServices/Feed.ashx.cs rename to demo/SampleWebApplication/WebHandlers/Feed.ashx.cs index 2df1fd3..5ab10e9 100644 --- a/demo/SampleWebApplication/WebServices/Feed.ashx.cs +++ b/demo/SampleWebApplication/WebHandlers/Feed.ashx.cs @@ -7,7 +7,7 @@ using SampleWebApplication.Options; using SampleWebApplication.Services; -namespace SampleWebApplication.WebServices +namespace SampleWebApplication.WebHandlers { /// /// Summary description for Feed @@ -20,12 +20,12 @@ public class FeedHandler : HttpTaskAsyncHandler public FeedHandler(ISyndicationClient syndicationClient, IOptions feedOptions) { this.syndicationClient = syndicationClient; - this.options = feedOptions.Value; + options = feedOptions.Value; } public override async Task ProcessRequestAsync(HttpContext context) { - var feed = await this.syndicationClient.GetSyndicationFeedAsync(this.options.Uri); + var feed = await syndicationClient.GetSyndicationFeedAsync(options.Uri); var response = new XElement("Feed", new XElement("Title", feed.Title.Text), diff --git a/src/Microsoft.Extensions.ServiceModel/DependencyInjection/SystemWebHostDependencyInjectionInstanceProvider.cs b/src/Microsoft.Extensions.ServiceModel/DependencyInjection/SystemWebHostDependencyInjectionInstanceProvider.cs new file mode 100644 index 0000000..e01950b --- /dev/null +++ b/src/Microsoft.Extensions.ServiceModel/DependencyInjection/SystemWebHostDependencyInjectionInstanceProvider.cs @@ -0,0 +1,26 @@ +using System.ServiceModel; +using System.ServiceModel.Channels; +using System.ServiceModel.Dispatcher; +using System.Web; + +namespace Microsoft.Extensions.ServiceModel.DependencyInjection +{ + internal sealed class SystemWebHostDependencyInjectionInstanceProvider : IInstanceProvider + { + public static readonly SystemWebHostDependencyInjectionInstanceProvider Shared = new SystemWebHostDependencyInjectionInstanceProvider(); + + public object GetInstance(InstanceContext instanceContext) + { + return GetInstance(instanceContext, null); + } + + public object GetInstance(InstanceContext instanceContext, Message message) + { + return HttpRuntime.WebObjectActivator.GetService(instanceContext.Host.Description.ServiceType); + } + + public void ReleaseInstance(InstanceContext instanceContext, object instance) + { + } + } +} diff --git a/src/Microsoft.Extensions.ServiceModel/DependencyInjection/SystemWebHostServiceBehaviorAttribute.cs b/src/Microsoft.Extensions.ServiceModel/DependencyInjection/SystemWebHostServiceBehaviorAttribute.cs new file mode 100644 index 0000000..271388e --- /dev/null +++ b/src/Microsoft.Extensions.ServiceModel/DependencyInjection/SystemWebHostServiceBehaviorAttribute.cs @@ -0,0 +1,165 @@ +using System; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Data; +using System.Globalization; +using System.ServiceModel; +using System.ServiceModel.Channels; +using System.ServiceModel.Description; +using System.ServiceModel.Dispatcher; + +namespace Microsoft.Extensions.ServiceModel.DependencyInjection +{ + [System.AttributeUsage(System.AttributeTargets.Class)] + public sealed class SystemWebHostServiceBehaviorAttribute : Attribute, IServiceBehavior + { + private readonly ServiceBehaviorAttribute serviceBehaviorAttribute; + private readonly IServiceBehavior serviceBehavior; + + public SystemWebHostServiceBehaviorAttribute() + { + this.serviceBehaviorAttribute = new ServiceBehaviorAttribute(); + this.serviceBehavior = this.serviceBehaviorAttribute as IServiceBehavior; + } + + [DefaultValue(null)] + public string Name + { + get => this.serviceBehaviorAttribute.Name; + set => this.serviceBehaviorAttribute.Name = value; + } + + [DefaultValue(null)] + public string Namespace + { + get => this.serviceBehaviorAttribute.Namespace; + set => this.serviceBehaviorAttribute.Namespace = value; + } + + [DefaultValue(AddressFilterMode.Exact)] + public AddressFilterMode AddressFilterMode + { + get => this.serviceBehaviorAttribute.AddressFilterMode; + set => this.serviceBehaviorAttribute.AddressFilterMode = value; + } + + [DefaultValue(true)] + public bool AutomaticSessionShutdown + { + get => this.serviceBehaviorAttribute.AutomaticSessionShutdown; + set => this.serviceBehaviorAttribute.AutomaticSessionShutdown = value; + } + + [DefaultValue(null)] + public string ConfigurationName + { + get => this.serviceBehaviorAttribute.ConfigurationName; + set => this.serviceBehaviorAttribute.ConfigurationName = value; + } + + public System.Transactions.IsolationLevel TransactionIsolationLevel + { + get => this.serviceBehaviorAttribute.TransactionIsolationLevel; + set => this.serviceBehaviorAttribute.TransactionIsolationLevel = value; + } + + [DefaultValue(false)] + public bool IncludeExceptionDetailInFaults + { + get => this.serviceBehaviorAttribute.IncludeExceptionDetailInFaults; + set => this.serviceBehaviorAttribute.IncludeExceptionDetailInFaults = value; + } + + [DefaultValue(ConcurrencyMode.Single)] + public ConcurrencyMode ConcurrencyMode + { + get => this.serviceBehaviorAttribute.ConcurrencyMode; + set => this.serviceBehaviorAttribute.ConcurrencyMode = value; + } + + [DefaultValue(false)] + public bool EnsureOrderedDispatch + { + get => this.serviceBehaviorAttribute.EnsureOrderedDispatch; + set => this.serviceBehaviorAttribute.EnsureOrderedDispatch = value; + } + + [DefaultValue(InstanceContextMode.PerSession)] + public InstanceContextMode InstanceContextMode + { + get => this.serviceBehaviorAttribute.InstanceContextMode; + set => this.serviceBehaviorAttribute.InstanceContextMode = value; + } + + public bool ReleaseServiceInstanceOnTransactionComplete + { + get => this.serviceBehaviorAttribute.ReleaseServiceInstanceOnTransactionComplete; + set => this.serviceBehaviorAttribute.ReleaseServiceInstanceOnTransactionComplete = value; + } + + public bool TransactionAutoCompleteOnSessionClose + { + get => this.serviceBehaviorAttribute.TransactionAutoCompleteOnSessionClose; + set => this.serviceBehaviorAttribute.TransactionAutoCompleteOnSessionClose = value; + } + + public string TransactionTimeout + { + get => this.serviceBehaviorAttribute.TransactionTimeout; + set => this.serviceBehaviorAttribute.TransactionTimeout = value; + } + + [DefaultValue(true)] + public bool ValidateMustUnderstand + { + get => this.serviceBehaviorAttribute.ValidateMustUnderstand; + set => this.serviceBehaviorAttribute.ValidateMustUnderstand = value; + } + + [DefaultValue(false)] + public bool IgnoreExtensionDataObject + { + get => this.serviceBehaviorAttribute.IgnoreExtensionDataObject; + set => this.serviceBehaviorAttribute.IgnoreExtensionDataObject = value; + } + + [DefaultValue(int.MaxValue)] + public int MaxItemsInObjectGraph + { + get => this.serviceBehaviorAttribute.MaxItemsInObjectGraph; + set => this.serviceBehaviorAttribute.MaxItemsInObjectGraph = value; + } + + [DefaultValue(true)] + public bool UseSynchronizationContext + { + get => this.serviceBehaviorAttribute.UseSynchronizationContext; + set => this.serviceBehaviorAttribute.UseSynchronizationContext = value; + } + + void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) + { + this.serviceBehavior.Validate(serviceDescription, serviceHostBase); + } + + void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection endpoints, BindingParameterCollection bindingParameters) + { + this.serviceBehavior.AddBindingParameters(serviceDescription, serviceHostBase, endpoints, bindingParameters); + } + + void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) + { + foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers) + { + var dispatcher = cdb as ChannelDispatcher; + foreach (EndpointDispatcher endpointDispatcher in dispatcher.Endpoints) + { + if (!endpointDispatcher.IsSystemEndpoint) + { + endpointDispatcher.DispatchRuntime.InstanceProvider = SystemWebHostDependencyInjectionInstanceProvider.Shared; + } + } + } + } + } +} diff --git a/src/Microsoft.Extensions.ServiceModel/Microsoft.Extensions.ServiceModel.csproj b/src/Microsoft.Extensions.ServiceModel/Microsoft.Extensions.ServiceModel.csproj new file mode 100644 index 0000000..7f9cfc4 --- /dev/null +++ b/src/Microsoft.Extensions.ServiceModel/Microsoft.Extensions.ServiceModel.csproj @@ -0,0 +1,13 @@ + + + + net472 + + + + + + + + +