Migration from WCF Web API to Web API
Migration from WCF Web API to Web API
This commit is contained in:
Родитель
4252abe61b
Коммит
ac72681132
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<solution>
|
||||
<add key="disableSourceControlIntegration" value="true" />
|
||||
</solution>
|
||||
</configuration>
|
|
@ -0,0 +1,71 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>
|
||||
|
||||
<!-- Windows specific commands -->
|
||||
<NuGetToolsPath Condition=" '$(OS)' == 'Windows_NT'">$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
|
||||
<PackagesConfig Condition=" '$(OS)' == 'Windows_NT'">$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>
|
||||
<PackagesDir Condition=" '$(OS)' == 'Windows_NT'">$([System.IO.Path]::Combine($(SolutionDir), "packages"))</PackagesDir>
|
||||
|
||||
<!-- We need to launch nuget.exe with the mono command if we're not on windows -->
|
||||
<NuGetToolsPath Condition=" '$(OS)' != 'Windows_NT'">$(SolutionDir).nuget</NuGetToolsPath>
|
||||
<PackagesConfig Condition=" '$(OS)' != 'Windows_NT' ">packages.config</PackagesConfig>
|
||||
<PackagesDir Condition=" '$(OS)' != 'Windows_NT'">$(SolutionDir)packages</PackagesDir>
|
||||
|
||||
<!-- NuGet command -->
|
||||
<NuGetExePath>$(NuGetToolsPath)\nuget.exe</NuGetExePath>
|
||||
<NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
|
||||
<NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 $(NuGetExePath)</NuGetCommand>
|
||||
|
||||
<PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>
|
||||
|
||||
<!-- Package sources used to restore packages. By default will used the registered sources under %APPDATA%\NuGet\NuGet.Config -->
|
||||
<PackageSources>""</PackageSources>
|
||||
|
||||
<!-- Enable the restore command to run before builds -->
|
||||
<RestorePackages Condition="$(RestorePackages) == ''">false</RestorePackages>
|
||||
|
||||
<!-- Property that enables building a package from a project -->
|
||||
<BuildPackage Condition="$(BuildPackage) == ''">false</BuildPackage>
|
||||
|
||||
<!-- Commands -->
|
||||
<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source $(PackageSources) -o "$(PackagesDir)"</RestoreCommand>
|
||||
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -p Configuration=$(Configuration) -o "$(PackageOutputDir)" -symbols</BuildCommand>
|
||||
|
||||
<!-- Make the build depend on restore packages -->
|
||||
<BuildDependsOn Condition="$(RestorePackages) == 'true'">
|
||||
RestorePackages;
|
||||
$(BuildDependsOn);
|
||||
</BuildDependsOn>
|
||||
|
||||
<!-- Make the build depend on restore packages -->
|
||||
<BuildDependsOn Condition="$(BuildPackage) == 'true'">
|
||||
$(BuildDependsOn);
|
||||
BuildPackage;
|
||||
</BuildDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="CheckPrerequisites">
|
||||
<!-- Raise an error if we're unable to locate nuget.exe -->
|
||||
<Error Condition="!Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
|
||||
</Target>
|
||||
|
||||
<Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">
|
||||
<Exec Command="$(RestoreCommand)"
|
||||
Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />
|
||||
|
||||
<Exec Command="$(RestoreCommand)"
|
||||
LogStandardErrorAsError="true"
|
||||
Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
|
||||
</Target>
|
||||
|
||||
<Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites">
|
||||
<Exec Command="$(BuildCommand)"
|
||||
Condition=" '$(OS)' != 'Windows_NT' " />
|
||||
|
||||
<Exec Command="$(BuildCommand)"
|
||||
LogStandardErrorAsError="true"
|
||||
Condition=" '$(OS)' == 'Windows_NT' " />
|
||||
</Target>
|
||||
</Project>
|
|
@ -12,6 +12,8 @@
|
|||
<AssemblyName>CloudServices.Identity.Membership</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\Source\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -35,45 +37,25 @@
|
|||
<Reference Include="AspNet.SuppressFormsRedirect">
|
||||
<HintPath>..\packages\aspnet.suppressformsredirect.0.0.1.4\lib\40\AspNet.SuppressFormsRedirect.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="EntityDataModel">
|
||||
<HintPath>..\packages\WebApi.OData.0.6.0\lib\40-Full\EntityDataModel.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ApplicationServer.Http">
|
||||
<HintPath>..\packages\WebApi.0.6.0\lib\40-Full\Microsoft.ApplicationServer.Http.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ApplicationServer.HttpEnhancements">
|
||||
<HintPath>..\packages\WebApi.Enhancements.0.6.0\lib\40-Full\Microsoft.ApplicationServer.HttpEnhancements.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Data.Spatial">
|
||||
<HintPath>..\packages\WebApi.OData.0.6.0\lib\40-Full\Microsoft.Data.Spatial.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Json">
|
||||
<HintPath>..\packages\JsonValue.0.6.0\lib\40\Microsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Net.Http.Formatting">
|
||||
<HintPath>..\packages\HttpClient.0.6.0\lib\40\Microsoft.Net.Http.Formatting.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Net.Http.Formatting.OData">
|
||||
<HintPath>..\packages\WebApi.OData.0.6.0\lib\40-Full\Microsoft.Net.Http.Formatting.OData.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Runtime.Serialization.Internal">
|
||||
<HintPath>..\packages\WebApi.0.6.0\lib\40-Full\Microsoft.Runtime.Serialization.Internal.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Server.Common">
|
||||
<HintPath>..\packages\WebApi.0.6.0\lib\40-Full\Microsoft.Server.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ServiceModel.Internal">
|
||||
<HintPath>..\packages\WebApi.0.6.0\lib\40-Full\Microsoft.ServiceModel.Internal.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.OData">
|
||||
<HintPath>..\packages\WebApi.OData.0.6.0\lib\40-Full\System.Data.OData.dll</HintPath>
|
||||
<Reference Include="System.Json, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Json.4.0.20126.16343\lib\net40\System.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http">
|
||||
<HintPath>..\packages\HttpClient.0.6.0\lib\40\System.Net.Http.dll</HintPath>
|
||||
<Reference Include="System.Net.Http, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Net.Http.2.0.20126.16343\lib\net40\System.Net.Http.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Net.Http.Formatting.4.0.20126.16343\lib\net40\System.Net.Http.Formatting.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.WebRequest, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Net.Http.2.0.20126.16343\lib\net40\System.Net.Http.WebRequest.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
|
@ -81,42 +63,47 @@
|
|||
<Reference Include="System.ServiceModel.Web" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.ApplicationServices" />
|
||||
<Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\AspNetWebApi.Core.4.0.20126.16343\lib\net40\System.Web.Http.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Http.Common, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Web.Http.Common.4.0.20126.16343\lib\net40\System.Web.Http.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Http.WebHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\AspNetWebApi.4.0.20126.16343\lib\net40\System.Web.Http.WebHost.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="WebApi.Membership">
|
||||
<HintPath>..\packages\WebApi.Membership.0.0.3.0\lib\40\WebApi.Membership.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ConfigurationExtensions.cs" />
|
||||
<Compile Include="Constants.cs" />
|
||||
<Compile Include="Properties\GlobalSuppressions.cs" />
|
||||
<Compile Include="MembershipService.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controllers\MembershipController.cs" />
|
||||
<Compile Include="RouteExtensions.cs" />
|
||||
<Compile Include="User.cs" />
|
||||
<Compile Include="LogOn.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="WebApi.Membership\System\AuthenticateAttribute.cs" />
|
||||
<Compile Include="WebApi.Membership\System\ControllerFilteredMessageProcessingHandler.cs" />
|
||||
<Compile Include="WebApi.Membership\System\HttpRequestMessageExtensions.cs" />
|
||||
<Compile Include="WebApi.Membership\System\MembershipAuthenticationHandler.cs" />
|
||||
<Compile Include="WebApi.Membership\System\PrincipalHelper.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>$(ProjectDir)..\NuGet\NuGet.exe install $(ProjectDir)packages.config -OutputDirectory $(ProjectDir)..\packages\</PreBuildEvent>
|
||||
<PreBuildEvent></PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.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">
|
||||
|
|
|
@ -16,34 +16,18 @@
|
|||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Identity.Membership
|
||||
{
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.ApplicationServer.Http;
|
||||
using Microsoft.Net.Http;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
|
||||
internal static class ConfigurationExtensions
|
||||
{
|
||||
internal static HttpConfiguration AddDelegatingHandlers(this HttpConfiguration config, params Type[] handlers)
|
||||
internal static HttpConfiguration AddDelegatingHandlers(this HttpConfiguration config, params DelegatingHandler[] handlers)
|
||||
{
|
||||
if (handlers != null)
|
||||
handlers.ToList().ForEach(t => config.MessageHandlers.Add(t));
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
internal static HttpConfiguration AddRequestHandlers(this HttpConfiguration config)
|
||||
{
|
||||
var requestHandlers = config.RequestHandlers;
|
||||
|
||||
config.RequestHandlers = (c, e, od) =>
|
||||
{
|
||||
if (requestHandlers != null)
|
||||
requestHandlers(c, e, od); // Original request handler
|
||||
|
||||
var filterAttribute = od.Attributes.Where(a => typeof(AuthenticateAttribute).IsAssignableFrom(a.GetType())).Cast<AuthenticateAttribute>().ToList();
|
||||
|
||||
filterAttribute.ForEach(a => c.Add(new MembershipAuthenticateUserOperationHandler()));
|
||||
};
|
||||
handlers.ToList().ForEach(t => config.MessageHandlers.Add(t));
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
|
|
@ -14,13 +14,14 @@
|
|||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Identity.Membership
|
||||
{
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
|
||||
internal abstract class FuncBasedFilterAttribute : Attribute
|
||||
public static class Constants
|
||||
{
|
||||
public abstract Func<HttpRequestMessage, bool> Filter { get; }
|
||||
public const string InvalidCredentialsMessage = "Invalid credentials.";
|
||||
|
||||
public const string InvalidUserInformation = "Invalid user information.";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,38 +19,30 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Identity.Membership
|
|||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Activation;
|
||||
using System.ServiceModel.Web;
|
||||
using System.Web.Http;
|
||||
using System.Web.Security;
|
||||
using Microsoft.ApplicationServer.Http.Dispatcher;
|
||||
using Microsoft.Net.Http;
|
||||
using Properties;
|
||||
|
||||
[ServiceContract]
|
||||
[ServiceBehavior(IncludeExceptionDetailInFaults = false)]
|
||||
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
|
||||
public class MembershipService
|
||||
public class MembershipController : ApiController
|
||||
{
|
||||
private readonly MembershipProvider membershipProvider;
|
||||
|
||||
public MembershipService()
|
||||
public MembershipController()
|
||||
: this(Membership.Provider)
|
||||
{
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public MembershipService(MembershipProvider membershipProvider)
|
||||
public MembershipController(MembershipProvider membershipProvider)
|
||||
{
|
||||
this.membershipProvider = membershipProvider ?? Membership.Provider;
|
||||
}
|
||||
|
||||
[WebInvoke(UriTemplate = "logon", Method = "POST")]
|
||||
public HttpResponseMessage LogOnUser(LogOn logOn)
|
||||
[HttpPost]
|
||||
public HttpResponseMessage Logon(LogOn logOn)
|
||||
{
|
||||
if ((logOn == null) || string.IsNullOrWhiteSpace(logOn.UserName) || string.IsNullOrWhiteSpace(logOn.Password))
|
||||
{
|
||||
throw WebException(Resources.InvalidCredentialsMessage, HttpStatusCode.BadRequest);
|
||||
throw WebException(Constants.InvalidCredentialsMessage, HttpStatusCode.BadRequest);
|
||||
}
|
||||
|
||||
bool isValidUser;
|
||||
|
@ -65,19 +57,19 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Identity.Membership
|
|||
|
||||
if (!isValidUser)
|
||||
{
|
||||
throw WebException(Resources.InvalidCredentialsMessage, HttpStatusCode.Unauthorized);
|
||||
throw WebException(HttpStatusCode.Unauthorized);
|
||||
}
|
||||
|
||||
var token = this.GenerateMembershipToken(logOn.UserName);
|
||||
return new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(token) };
|
||||
}
|
||||
|
||||
[Authenticate, WebGet(UriTemplate = "username")]
|
||||
public HttpResponseMessage UserName(HttpRequestMessage message)
|
||||
[Authenticate, HttpGet]
|
||||
public HttpResponseMessage UserName()
|
||||
{
|
||||
try
|
||||
{
|
||||
var username = message.User().Identity.Name;
|
||||
var username = this.Request.User().Identity.Name;
|
||||
|
||||
if (username != null)
|
||||
{
|
||||
|
@ -85,7 +77,10 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Identity.Membership
|
|||
if (user != null)
|
||||
{
|
||||
var response = new HttpResponseMessage(HttpStatusCode.OK)
|
||||
{ Content = new StringContent(user.UserName) };
|
||||
{
|
||||
Content = new StringContent(user.UserName)
|
||||
};
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
@ -98,14 +93,14 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Identity.Membership
|
|||
}
|
||||
}
|
||||
|
||||
[WebInvoke(UriTemplate = "users", Method = "PUT")]
|
||||
public HttpResponseMessage<User> CreateUser(User user)
|
||||
[HttpPut]
|
||||
public HttpResponseMessage<User> Users(User user)
|
||||
{
|
||||
MembershipCreateStatus createStatus;
|
||||
|
||||
if ((user == null) || string.IsNullOrWhiteSpace(user.Name) || string.IsNullOrWhiteSpace(user.Email) || string.IsNullOrWhiteSpace(user.Password))
|
||||
{
|
||||
throw WebException(Resources.InvalidUserInformation, HttpStatusCode.BadRequest);
|
||||
throw WebException(Constants.InvalidUserInformation, HttpStatusCode.BadRequest);
|
||||
}
|
||||
|
||||
this.membershipProvider.CreateUser(user.Name, user.Password, user.Email, null, null, true, null, out createStatus);
|
||||
|
@ -130,7 +125,13 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Identity.Membership
|
|||
|
||||
private static HttpResponseException WebException(string message, HttpStatusCode code)
|
||||
{
|
||||
var result = new HttpResponseException(new HttpResponseMessage(code) { Content = new StringContent(message) });
|
||||
var response = new HttpResponseMessage(code);
|
||||
if (!string.IsNullOrEmpty(message))
|
||||
{
|
||||
response.Content = new StringContent(message);
|
||||
}
|
||||
|
||||
var result = new HttpResponseException(response);
|
||||
|
||||
if (code == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
|
@ -139,5 +140,10 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Identity.Membership
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static HttpResponseException WebException(HttpStatusCode code)
|
||||
{
|
||||
return WebException(null, code);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
// ----------------------------------------------------------------------------------
|
||||
// Microsoft Developer & Platform Evangelism
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ----------------------------------------------------------------------------------
|
||||
// The example companies, organizations, products, domain names,
|
||||
// e-mail addresses, logos, people, places, and events depicted
|
||||
// herein are fictitious. No association with any real company,
|
||||
// organization, product, domain name, email address, logo, person,
|
||||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.235
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Identity.Membership.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.WindowsAzure.Samples.CloudServices.Identity.Membership.Properties.Resou" +
|
||||
"rces", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Invalid credentials..
|
||||
/// </summary>
|
||||
internal static string InvalidCredentialsMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("InvalidCredentialsMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Invalid user information..
|
||||
/// </summary>
|
||||
internal static string InvalidUserInformation {
|
||||
get {
|
||||
return ResourceManager.GetString("InvalidUserInformation", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="InvalidCredentialsMessage" xml:space="preserve">
|
||||
<value>Invalid credentials.</value>
|
||||
</data>
|
||||
<data name="InvalidUserInformation" xml:space="preserve">
|
||||
<value>Invalid user information.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -16,16 +16,24 @@
|
|||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Identity.Membership
|
||||
{
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using System.Web.Routing;
|
||||
using Microsoft.ApplicationServer.Http;
|
||||
|
||||
public static class RouteExtensions
|
||||
{
|
||||
public static void MapAuthenticationServiceRoute(this RouteCollection routes, string prefix, params Type[] handlers)
|
||||
public static void MapAuthenticationServiceRoute(this RouteCollection routes, string prefix, params DelegatingHandler[] handlers)
|
||||
{
|
||||
var configuration = new HttpConfiguration().AddDelegatingHandlers(handlers).AddRequestHandlers();
|
||||
routes.MapServiceRoute<MembershipService>(prefix, configuration);
|
||||
var currentConfiguration = GlobalConfiguration.Configuration;
|
||||
|
||||
// Handlers
|
||||
currentConfiguration.AddDelegatingHandlers(handlers);
|
||||
|
||||
// Routes
|
||||
routes.MapHttpRoute(
|
||||
name: prefix,
|
||||
routeTemplate: prefix + "/{action}",
|
||||
defaults: new { Controller = "Membership" });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,27 +14,39 @@
|
|||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
||||
namespace System.Net.Http
|
||||
{
|
||||
using System.Net.Http;
|
||||
using System;
|
||||
using System.Web;
|
||||
using ApplicationServer.Http.Dispatcher;
|
||||
using System.Web.Http;
|
||||
using System.Web.Http.Controllers;
|
||||
using System.Web.Http.Filters;
|
||||
using System.Web.Security;
|
||||
|
||||
internal class FuncBasedOperationHandler : HttpOperationHandler<HttpRequestMessage, HttpRequestMessage>
|
||||
public class AuthenticateAttribute : AuthorizationFilterAttribute
|
||||
{
|
||||
private readonly FuncBasedFilterAttribute filterAttribute;
|
||||
|
||||
public FuncBasedOperationHandler(FuncBasedFilterAttribute filterAttribute)
|
||||
: base("response")
|
||||
public override void OnAuthorization(HttpActionContext actionContext)
|
||||
{
|
||||
this.filterAttribute = filterAttribute;
|
||||
var input = actionContext.Request;
|
||||
var principal = PrincipalHelper.GetPrincipalFromHttpRequest(input);
|
||||
if (principal == null)
|
||||
{
|
||||
throw UnauthorizedException();
|
||||
}
|
||||
|
||||
var user = Membership.GetUser(principal.Identity.Name);
|
||||
if (user == null)
|
||||
{
|
||||
throw UnauthorizedException();
|
||||
}
|
||||
|
||||
PrincipalHelper.SetPrincipal(input, principal);
|
||||
|
||||
base.OnAuthorization(actionContext);
|
||||
}
|
||||
|
||||
protected override HttpRequestMessage OnHandle(HttpRequestMessage input)
|
||||
private static Exception UnauthorizedException()
|
||||
{
|
||||
if (this.filterAttribute.Filter(input))
|
||||
return input;
|
||||
|
||||
// HACK: Prevent ASP.NET Forms Authentication to redirect the user to the login page.
|
||||
// This thread-safe approach adds a header with the suppression to be read on the
|
||||
// OnEndRequest event of the pipelien. In order to fully support the supression you should have the ASP.NET Module
|
||||
|
@ -42,7 +54,7 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
|||
var response = new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
|
||||
response.Headers.Add(SuppressFormsAuthenticationRedirectModule.SuppressFormsHeaderName, "true");
|
||||
|
||||
throw new HttpResponseException(response);
|
||||
return new HttpResponseException(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
// ----------------------------------------------------------------------------------
|
||||
// Microsoft Developer & Platform Evangelism
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ----------------------------------------------------------------------------------
|
||||
// The example companies, organizations, products, domain names,
|
||||
// e-mail addresses, logos, people, places, and events depicted
|
||||
// herein are fictitious. No association with any real company,
|
||||
// organization, product, domain name, email address, logo, person,
|
||||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Net.Http
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Web.Http;
|
||||
|
||||
public abstract class ControllerFilteredMessageProcessingHandler : MessageProcessingHandler
|
||||
{
|
||||
public IList<string> ConfiguredControllers { get; set; }
|
||||
|
||||
protected abstract HttpRequestMessage ProcessRequestHandler(HttpRequestMessage request, CancellationToken cancellationToken);
|
||||
|
||||
protected override HttpRequestMessage ProcessRequest(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
var routeData = request.GetRouteData();
|
||||
var controllerName = routeData.Values.ContainsKey("controller") ?
|
||||
routeData.Values["controller"].ToString() :
|
||||
string.Empty;
|
||||
|
||||
if (this.ConfiguredControllers == null ||
|
||||
this.ConfiguredControllers.Any(c => c.Equals(controllerName, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return this.ProcessRequestHandler(request, cancellationToken);
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
protected override HttpResponseMessage ProcessResponse(HttpResponseMessage response, CancellationToken cancellationToken)
|
||||
{
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
// ----------------------------------------------------------------------------------
|
||||
// Microsoft Developer & Platform Evangelism
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ----------------------------------------------------------------------------------
|
||||
// The example companies, organizations, products, domain names,
|
||||
// e-mail addresses, logos, people, places, and events depicted
|
||||
// herein are fictitious. No association with any real company,
|
||||
// organization, product, domain name, email address, logo, person,
|
||||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
// <copyright file="HttpRequestMessageExtensions.cs" company="open-source" >
|
||||
// Copyright binary (c) 2011 by Johnny Halife, Juan Pablo Garcia, Mauro Krikorian, Mariano Converti,
|
||||
// Damian Martinez, Nico Bello, and Ezequiel Morito
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted.
|
||||
//
|
||||
// The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
// </copyright>
|
||||
|
||||
namespace System.Net.Http
|
||||
{
|
||||
using System.Security.Principal;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
|
||||
/// <summary>
|
||||
/// HttpRequestMessage extension methods.
|
||||
/// </summary>
|
||||
public static class HttpRequestMessageExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the IPrincipal instance authenticated and stored by the MembershipAuthenticationHandler
|
||||
/// on the ongoing request.
|
||||
/// </summary>
|
||||
/// <param name="message">this (request)</param>
|
||||
/// <returns>IPrincipal instance authenticated and stored by the MembershipAuthenticationHandler</returns>
|
||||
public static IPrincipal User(this HttpRequestMessage message)
|
||||
{
|
||||
if (message != null)
|
||||
{
|
||||
return message.Properties[MembershipAuthenticationHandler.MessagePrincipalKey] as IPrincipal;
|
||||
}
|
||||
|
||||
if (Thread.CurrentPrincipal != null)
|
||||
{
|
||||
return Thread.CurrentPrincipal;
|
||||
}
|
||||
|
||||
if (HttpContext.Current != null)
|
||||
{
|
||||
return HttpContext.Current.User;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
// ----------------------------------------------------------------------------------
|
||||
// Microsoft Developer & Platform Evangelism
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ----------------------------------------------------------------------------------
|
||||
// The example companies, organizations, products, domain names,
|
||||
// e-mail addresses, logos, people, places, and events depicted
|
||||
// herein are fictitious. No association with any real company,
|
||||
// organization, product, domain name, email address, logo, person,
|
||||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
// <copyright file="MembershipAuthenticationHandler.cs" company="open-source" >
|
||||
// Copyright binary (c) 2011 by Johnny Halife, Juan Pablo Garcia, Mauro Krikorian, Mariano Converti,
|
||||
// Damian Martinez, Nico Bello, and Ezequiel Morito
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted.
|
||||
//
|
||||
// The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
// </copyright>
|
||||
|
||||
namespace System.Net.Http
|
||||
{
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using System.Web.Http;
|
||||
using System.Web.Security;
|
||||
|
||||
/// <summary>
|
||||
/// Authenticates the ongoing request using Membership and Forms Authentication cookie.
|
||||
/// Grabs the forms authentication ticket token from the cookie header and performs the authentication
|
||||
/// due to WebApi requirement for ASP.NET we're also suppressing Forms Redirect by leveraging
|
||||
/// aspnet.suppressformsredirect Package.
|
||||
/// </summary>
|
||||
public class MembershipAuthenticationHandler : ControllerFilteredMessageProcessingHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Key used to stuff the Request with the authenticated principal after a
|
||||
/// successful login.
|
||||
/// </summary>
|
||||
public const string MessagePrincipalKey = "identity.currentprincipal";
|
||||
|
||||
/// <summary>
|
||||
/// Performs Membership Authentication of the on going request. Turns Membership authentication into mandatory.
|
||||
/// </summary>
|
||||
/// <param name="request">Ongoing request</param>
|
||||
/// <param name="cancellationToken">Async Cancellation token</param>
|
||||
/// <returns>The HTTP request message that was processed</returns>
|
||||
protected override HttpRequestMessage ProcessRequestHandler(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
var principal = PrincipalHelper.GetPrincipalFromHttpRequest(request);
|
||||
if (principal == null)
|
||||
{
|
||||
this.Unauthorized();
|
||||
}
|
||||
|
||||
var user = Membership.GetUser(principal.Identity.Name);
|
||||
if (user == null)
|
||||
{
|
||||
this.Unauthorized();
|
||||
}
|
||||
|
||||
PrincipalHelper.SetPrincipal(request, principal);
|
||||
}
|
||||
catch
|
||||
{
|
||||
this.Unauthorized();
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
private void Unauthorized()
|
||||
{
|
||||
// HACK: Prevent ASP.NET Forms Authentication to redirect the user to the login page.
|
||||
// This thread-safe approach adds a header with the suppression to be read on the
|
||||
// OnEndRequest event of the pipelien. In order to fully support the supression you should have the ASP.NET Module
|
||||
// that does this (SuppressFormsAuthenticationRedirectModule).
|
||||
var response = new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
|
||||
response.Headers.Add(SuppressFormsAuthenticationRedirectModule.SuppressFormsHeaderName, "true");
|
||||
|
||||
throw new HttpResponseException(response);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
// ----------------------------------------------------------------------------------
|
||||
// Microsoft Developer & Platform Evangelism
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ----------------------------------------------------------------------------------
|
||||
// The example companies, organizations, products, domain names,
|
||||
// e-mail addresses, logos, people, places, and events depicted
|
||||
// herein are fictitious. No association with any real company,
|
||||
// organization, product, domain name, email address, logo, person,
|
||||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Net.Http
|
||||
{
|
||||
using System;
|
||||
using System.Security.Principal;
|
||||
using System.Web.Security;
|
||||
|
||||
public static class PrincipalHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks, extracs, and parses the SimpleWebToken from the Authentication Header.
|
||||
/// </summary>
|
||||
/// <param name="request">Ongoing request.</param>
|
||||
/// <returns>A parsed SimpleWebToken.</returns>
|
||||
internal static FormsAuthenticationTicket ExtractTicketFromHeader(HttpRequestMessage request)
|
||||
{
|
||||
var authorizationHeader = request.Headers.Authorization;
|
||||
|
||||
if (authorizationHeader != null && authorizationHeader.Scheme.Equals("Membership", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var ticket = FormsAuthentication.Decrypt(authorizationHeader.Parameter);
|
||||
|
||||
if (ticket != null && !ticket.Expired)
|
||||
{
|
||||
return ticket;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static IPrincipal GetPrincipalFromHttpRequest(HttpRequestMessage request)
|
||||
{
|
||||
var ticket = PrincipalHelper.ExtractTicketFromHeader(request);
|
||||
if (ticket == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new GenericPrincipal(new FormsIdentity(ticket), new string[0]);
|
||||
}
|
||||
|
||||
internal static void SetPrincipal(HttpRequestMessage request, IPrincipal principal)
|
||||
{
|
||||
// We authenticate the ongoing thread but also we stuff the principal on the message
|
||||
// after a brief chat with Glenn Block we understood that the only way to authenticate
|
||||
// a request and continue using it is to stuff it's authenticated user throught on
|
||||
// the message properties.
|
||||
request.Properties[MembershipAuthenticationHandler.MessagePrincipalKey] = principal;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="aspnet.suppressformsredirect" version="0.0.1.4" />
|
||||
<package id="HttpClient" version="0.6.0" />
|
||||
<package id="JsonValue" version="0.6.0" />
|
||||
<package id="WebApi" version="0.6.0" />
|
||||
<package id="WebApi.All" version="0.6.0" />
|
||||
<package id="WebApi.Enhancements" version="0.6.0" />
|
||||
<package id="WebApi.Membership" version="0.0.3.0" />
|
||||
<package id="WebApi.OData" version="0.6.0" />
|
||||
<package id="AspNetWebApi" version="4.0.20126.16343" />
|
||||
<package id="AspNetWebApi.Core" version="4.0.20126.16343" />
|
||||
<package id="System.Json" version="4.0.20126.16343" />
|
||||
<package id="System.Net.Http" version="2.0.20126.16343" />
|
||||
<package id="System.Net.Http.Formatting" version="4.0.20126.16343" />
|
||||
<package id="System.Web.Http.Common" version="4.0.20126.16343" />
|
||||
<package id="WebApi.Membership" version="0.0.3.2" />
|
||||
</packages>
|
|
@ -12,6 +12,8 @@
|
|||
<AssemblyName>CloudServices.Notifications.WindowsAzure</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\Source\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -66,6 +68,7 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.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">
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
<AssemblyName>CloudServices.Notifications.Common</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\Source\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -45,6 +47,7 @@
|
|||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.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">
|
||||
|
|
|
@ -22,13 +22,17 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
|||
{
|
||||
public virtual string ApplicationId { get; set; }
|
||||
|
||||
public virtual string DeviceId { get; set; }
|
||||
public virtual string TileId { get; set; }
|
||||
|
||||
public virtual string ClientId { get; set; }
|
||||
|
||||
public string ChannelUri { get; set; }
|
||||
|
||||
public string UserId { get; set; }
|
||||
|
||||
public string Expiry { get; set; }
|
||||
public DateTime ExpirationTime { get; set; }
|
||||
|
||||
public string DeviceType { get; set; }
|
||||
|
||||
public static T To<T>(Endpoint endpoint) where T : Endpoint
|
||||
{
|
||||
|
@ -38,12 +42,14 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
|||
var destination = Activator.CreateInstance<T>();
|
||||
|
||||
destination.ApplicationId = endpoint.ApplicationId;
|
||||
destination.TileId = endpoint.TileId;
|
||||
destination.ClientId = endpoint.ClientId;
|
||||
destination.ChannelUri = endpoint.ChannelUri;
|
||||
destination.DeviceId = endpoint.DeviceId;
|
||||
destination.Expiry = endpoint.Expiry;
|
||||
destination.UserId = endpoint.UserId;
|
||||
destination.ExpirationTime = endpoint.ExpirationTime;
|
||||
destination.DeviceType = endpoint.DeviceType;
|
||||
|
||||
return destination;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,8 +27,10 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
|||
|
||||
Endpoint Find(Func<Endpoint, bool> filterExpression);
|
||||
|
||||
Endpoint Find(string applicationId, string tileId, string clientId);
|
||||
|
||||
void InsertOrUpdate(Endpoint endpoint);
|
||||
|
||||
void Delete(string applicationId, string deviceId);
|
||||
void Delete(string applicationId, string tileId, string clientId);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,6 +12,8 @@
|
|||
<AssemblyName>CloudServices.Notifications.Sql</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\Source\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -32,53 +34,41 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="EntityDataModel">
|
||||
<HintPath>..\packages\WebApi.OData.0.6.0\lib\40-Full\EntityDataModel.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="EntityFramework, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\EntityFramework.4.2.0.0\lib\net40\EntityFramework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ApplicationServer.Http">
|
||||
<HintPath>..\packages\WebApi.0.6.0\lib\40-Full\Microsoft.ApplicationServer.Http.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ApplicationServer.HttpEnhancements">
|
||||
<HintPath>..\packages\WebApi.Enhancements.0.6.0\lib\40-Full\Microsoft.ApplicationServer.HttpEnhancements.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Data.Spatial">
|
||||
<HintPath>..\packages\WebApi.OData.0.6.0\lib\40-Full\Microsoft.Data.Spatial.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Json">
|
||||
<HintPath>..\packages\JsonValue.0.6.0\lib\40\Microsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Net.Http.Formatting">
|
||||
<HintPath>..\packages\HttpClient.0.6.0\lib\40\Microsoft.Net.Http.Formatting.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Net.Http.Formatting.OData">
|
||||
<HintPath>..\packages\WebApi.OData.0.6.0\lib\40-Full\Microsoft.Net.Http.Formatting.OData.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Runtime.Serialization.Internal">
|
||||
<HintPath>..\packages\WebApi.0.6.0\lib\40-Full\Microsoft.Runtime.Serialization.Internal.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Server.Common">
|
||||
<HintPath>..\packages\WebApi.0.6.0\lib\40-Full\Microsoft.Server.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ServiceModel.Internal">
|
||||
<HintPath>..\packages\WebApi.0.6.0\lib\40-Full\Microsoft.ServiceModel.Internal.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.Entity" />
|
||||
<Reference Include="System.Data.OData">
|
||||
<HintPath>..\packages\WebApi.OData.0.6.0\lib\40-Full\System.Data.OData.dll</HintPath>
|
||||
<Reference Include="System.Json, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Json.4.0.20126.16343\lib\net40\System.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\HttpClient.0.6.0\lib\40\System.Net.Http.dll</HintPath>
|
||||
<Reference Include="System.Net.Http, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Net.Http.2.0.20126.16343\lib\net40\System.Net.Http.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Net.Http.Formatting.4.0.20126.16343\lib\net40\System.Net.Http.Formatting.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.WebRequest, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Net.Http.2.0.20126.16343\lib\net40\System.Net.Http.WebRequest.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.ServiceModel.Activation" />
|
||||
<Reference Include="System.ServiceModel.Web" />
|
||||
<Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\AspNetWebApi.Core.4.0.20126.16343\lib\net40\System.Web.Http.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Http.Common, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Web.Http.Common.4.0.20126.16343\lib\net40\System.Web.Http.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
|
@ -106,8 +96,9 @@
|
|||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>$(ProjectDir)..\NuGet\NuGet.exe install $(ProjectDir)packages.config -OutputDirectory $(ProjectDir)..\packages\</PreBuildEvent>
|
||||
<PreBuildEvent></PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.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">
|
||||
|
|
|
@ -1,271 +0,0 @@
|
|||
<StyleCopSettings Version="105">
|
||||
<GlobalSettings>
|
||||
<StringProperty Name="MergeSettingsFiles">NoMerge</StringProperty>
|
||||
</GlobalSettings>
|
||||
<Parsers>
|
||||
<Parser ParserId="StyleCop.CSharp.CsParser">
|
||||
<ParserSettings>
|
||||
<BooleanProperty Name="AnalyzeDesignerFiles">False</BooleanProperty>
|
||||
<CollectionProperty Name="GeneratedFileFilters">
|
||||
<Value>\.g\.cs$</Value>
|
||||
<Value>\.generated\.cs$</Value>
|
||||
<Value>\.g\.i\.cs$</Value>
|
||||
</CollectionProperty>
|
||||
</ParserSettings>
|
||||
</Parser>
|
||||
</Parsers>
|
||||
<Analyzers>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.NamingRules">
|
||||
<AnalyzerSettings>
|
||||
<CollectionProperty Name="Hungarian">
|
||||
<Value>as</Value>
|
||||
<Value>do</Value>
|
||||
<Value>id</Value>
|
||||
<Value>if</Value>
|
||||
<Value>in</Value>
|
||||
<Value>is</Value>
|
||||
<Value>my</Value>
|
||||
<Value>no</Value>
|
||||
<Value>on</Value>
|
||||
<Value>to</Value>
|
||||
<Value>ui</Value>
|
||||
</CollectionProperty>
|
||||
</AnalyzerSettings>
|
||||
</Analyzer>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules">
|
||||
<Rules>
|
||||
<Rule Name="ElementsMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PartialElementsMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="EnumerationItemsMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationMustContainValidXml">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustHaveSummary">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PartialElementDocumentationMustHaveSummary">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustHaveSummaryText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PartialElementDocumentationMustHaveSummaryText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustNotHaveDefaultSummary">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParametersMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParameterDocumentationMustMatchElementParameters">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParameterDocumentationMustDeclareParameterName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParameterDocumentationMustHaveText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementReturnValueMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementReturnValueDocumentationMustHaveText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="VoidReturnValueMustNotBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParametersMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParametersMustBeDocumentedPartialClass">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParameterDocumentationMustMatchTypeParameters">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParameterDocumentationMustDeclareParameterName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParameterDocumentationMustHaveText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PropertySummaryDocumentationMustMatchAccessors">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PropertySummaryDocumentationMustOmitSetAccessorWithRestrictedAccess">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustNotBeCopiedAndPasted">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="SingleLineCommentsMustNotUseDocumentationStyleSlashes">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationTextMustNotBeEmpty">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationTextMustContainWhitespace">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationMustMeetCharacterPercentage">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationTextMustMeetMinimumCharacterLength">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ConstructorSummaryDocumentationMustBeginWithStandardText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DestructorSummaryDocumentationMustBeginWithStandardText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationHeadersMustNotContainBlankLines">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="IncludedDocumentationXPathDoesNotExist">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="IncludeNodeDoesNotContainValidFileAndPath">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileMustHaveHeader">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustShowCopyright">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustHaveCopyrightText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustContainFileName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderFileNameDocumentationMustMatchFileName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustHaveValidCompanyText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
</Rules>
|
||||
<AnalyzerSettings />
|
||||
</Analyzer>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.LayoutRules">
|
||||
<Rules>
|
||||
<Rule Name="CurlyBracketsForMultiLineStatementsMustNotShareLine">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="StatementMustNotBeOnSingleLine">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementMustNotBeOnSingleLine">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="CurlyBracketsMustNotBeOmitted">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="AllAccessorsMustBeMultiLineOrSingleLine">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
</Rules>
|
||||
<AnalyzerSettings />
|
||||
</Analyzer>
|
||||
</Analyzers>
|
||||
</StyleCopSettings>
|
|
@ -41,4 +41,4 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications.Sql
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -57,11 +57,16 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications.Sql
|
|||
}
|
||||
}
|
||||
|
||||
public Endpoint Find(string applicationId, string tileId, string clientId)
|
||||
{
|
||||
return this.Find(e => e.ApplicationId.Equals(applicationId) && e.TileId.Equals(tileId ?? string.Empty) && e.ClientId.Equals(clientId));
|
||||
}
|
||||
|
||||
public void InsertOrUpdate(Endpoint endpoint)
|
||||
{
|
||||
using (var context = this.CreateContext())
|
||||
{
|
||||
var storedEndpoint = this.Find(e => e.ApplicationId.Equals(endpoint.ApplicationId) && e.DeviceId.Equals(endpoint.DeviceId));
|
||||
var storedEndpoint = this.Find(endpoint.ApplicationId, endpoint.TileId, endpoint.ClientId);
|
||||
|
||||
if (storedEndpoint == null)
|
||||
{
|
||||
|
@ -74,7 +79,7 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications.Sql
|
|||
|
||||
// Update values
|
||||
updatableEndpoint.ChannelUri = endpoint.ChannelUri;
|
||||
updatableEndpoint.Expiry = endpoint.Expiry;
|
||||
updatableEndpoint.ExpirationTime = endpoint.ExpirationTime;
|
||||
updatableEndpoint.UserId = endpoint.UserId;
|
||||
}
|
||||
|
||||
|
@ -82,16 +87,25 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications.Sql
|
|||
}
|
||||
}
|
||||
|
||||
public void Delete(string applicationId, string deviceId)
|
||||
public void Delete(string applicationId, string tileId, string clientId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(applicationId))
|
||||
throw new ArgumentNullException("applicationId");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(clientId))
|
||||
throw new ArgumentNullException("clientId");
|
||||
|
||||
using (var context = this.CreateContext())
|
||||
{
|
||||
var storedEndpoint = this.Find(e => e.ApplicationId.Equals(applicationId) && e.DeviceId.Equals(deviceId));
|
||||
var storedEndpoint = this.Find(applicationId, tileId, clientId);
|
||||
|
||||
var removableEndpoint = Endpoint.To<SqlEndpointTableRow>(storedEndpoint);
|
||||
context.Endpoints.Attach(removableEndpoint);
|
||||
context.Endpoints.Remove(removableEndpoint);
|
||||
context.SaveChanges();
|
||||
if (storedEndpoint != null)
|
||||
{
|
||||
var removableEndpoint = Endpoint.To<SqlEndpointTableRow>(storedEndpoint);
|
||||
context.Endpoints.Attach(removableEndpoint);
|
||||
context.Endpoints.Remove(removableEndpoint);
|
||||
context.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,9 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications.Sql
|
|||
public override string ApplicationId { get; set; }
|
||||
|
||||
[Key, Column(Order = 1)]
|
||||
public override string DeviceId { get; set; }
|
||||
public override string TileId { get; set; }
|
||||
|
||||
[Key, Column(Order = 2)]
|
||||
public override string ClientId { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,10 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="AspNetWebApi.Core" version="4.0.20126.16343" />
|
||||
<package id="EntityFramework" version="4.2.0.0" />
|
||||
<package id="HttpClient" version="0.6.0" />
|
||||
<package id="JsonValue" version="0.6.0" />
|
||||
<package id="WebApi" version="0.6.0" />
|
||||
<package id="WebApi.All" version="0.6.0" />
|
||||
<package id="WebApi.Enhancements" version="0.6.0" />
|
||||
<package id="WebApi.OData" version="0.6.0" />
|
||||
<package id="System.Json" version="4.0.20126.16343" />
|
||||
<package id="System.Net.Http" version="2.0.20126.16343" />
|
||||
<package id="System.Net.Http.Formatting" version="4.0.20126.16343" />
|
||||
<package id="System.Web.Http.Common" version="4.0.20126.16343" />
|
||||
</packages>
|
|
@ -12,6 +12,8 @@
|
|||
<AssemblyName>CloudServices.Notifications</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\Source\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -35,53 +37,45 @@
|
|||
<Reference Include="AspNet.SuppressFormsRedirect">
|
||||
<HintPath>..\packages\aspnet.suppressformsredirect.0.0.1.4\lib\40\AspNet.SuppressFormsRedirect.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="EntityDataModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\WebApi.OData.0.6.0\lib\40-Full\EntityDataModel.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ApplicationServer.Http, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\WebApi.0.6.0\lib\40-Full\Microsoft.ApplicationServer.Http.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ApplicationServer.HttpEnhancements, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\WebApi.Enhancements.0.6.0\lib\40-Full\Microsoft.ApplicationServer.HttpEnhancements.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Data.Spatial, Version=4.99.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\WebApi.OData.0.6.0\lib\40-Full\Microsoft.Data.Spatial.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Json, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\JsonValue.0.6.0\lib\40\Microsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Net.Http.Formatting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\HttpClient.0.6.0\lib\40\Microsoft.Net.Http.Formatting.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Net.Http.Formatting.OData, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\WebApi.OData.0.6.0\lib\40-Full\Microsoft.Net.Http.Formatting.OData.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Runtime.Serialization.Internal, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\WebApi.0.6.0\lib\40-Full\Microsoft.Runtime.Serialization.Internal.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Server.Common, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\WebApi.0.6.0\lib\40-Full\Microsoft.Server.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ServiceModel.Internal, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\WebApi.0.6.0\lib\40-Full\Microsoft.ServiceModel.Internal.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.WindowsAzure.StorageClient, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.OData, Version=4.99.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\WebApi.OData.0.6.0\lib\40-Full\System.Data.OData.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.Services.Client" />
|
||||
<Reference Include="System.Json, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Json.4.0.20126.16343\lib\net40\System.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net" />
|
||||
<Reference Include="System.Net.Http, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\HttpClient.0.6.0\lib\40\System.Net.Http.dll</HintPath>
|
||||
<Reference Include="System.Net.Http, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Net.Http.2.0.20126.16343\lib\net40\System.Net.Http.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Net.Http.Formatting.4.0.20126.16343\lib\net40\System.Net.Http.Formatting.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.WebRequest, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Net.Http.2.0.20126.16343\lib\net40\System.Net.Http.WebRequest.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.ServiceModel.Activation" />
|
||||
<Reference Include="System.ServiceModel.Web" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\AspNetWebApi.Core.4.0.20126.16343\lib\net40\System.Web.Http.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Http.Common, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Web.Http.Common.4.0.20126.16343\lib\net40\System.Web.Http.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Http.WebHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\AspNetWebApi.4.0.20126.16343\lib\net40\System.Web.Http.WebHost.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
|
@ -89,23 +83,18 @@
|
|||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Constants.cs" />
|
||||
<Compile Include="Security\AuthenticateEndpointAttribute.cs" />
|
||||
<Compile Include="ConfigurationExtensions.cs" />
|
||||
<Compile Include="Security\AuthorizeRegistrationEndpointAttribute.cs" />
|
||||
<Compile Include="Security\AuthorizeManagementEndpointAttribute.cs" />
|
||||
<Compile Include="Security\FuncBasedOperationHandler.cs" />
|
||||
<Compile Include="Security\FuncBasedFilterAttribute.cs" />
|
||||
<Compile Include="Security\FuncBasedAuthorizationFilterAttribute.cs" />
|
||||
<Compile Include="Properties\GlobalSuppressions.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="RouteExtensions.cs" />
|
||||
<Compile Include="NotificationServiceConfig.cs" />
|
||||
<Compile Include="NotificationServiceContext.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="EndpointService.cs" />
|
||||
<Compile Include="Controllers\EndpointController.cs" />
|
||||
<Compile Include="WindowsAzure\DataServiceQueryExceptionExtensions.cs" />
|
||||
<Compile Include="WindowsAzure\EndpointTableRow.cs" />
|
||||
<Compile Include="WindowsAzure\WindowsAzureEndpointRepository.cs" />
|
||||
|
@ -115,12 +104,6 @@
|
|||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Core\Source\Common\Common.csproj">
|
||||
<Project>{0E6DD9F0-9B91-4D3F-9384-2C6B96734EE0}</Project>
|
||||
|
@ -133,11 +116,12 @@
|
|||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>$(ProjectDir)..\NuGet\NuGet.exe install $(ProjectDir)packages.config -OutputDirectory $(ProjectDir)..\packages\</PreBuildEvent>
|
||||
<PreBuildEvent></PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent></PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.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">
|
||||
|
|
|
@ -16,34 +16,17 @@
|
|||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
||||
{
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.ApplicationServer.Http;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
|
||||
internal static class ConfigurationExtensions
|
||||
{
|
||||
internal static HttpConfiguration AddDelegatingHandlers(this HttpConfiguration config, params Type[] handlers)
|
||||
internal static HttpConfiguration AddDelegatingHandlers(this HttpConfiguration config, params DelegatingHandler[] handlers)
|
||||
{
|
||||
handlers.ToList().ForEach(t => config.MessageHandlers.Add(t));
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
internal static HttpConfiguration AddRequestHandlers(this HttpConfiguration config)
|
||||
{
|
||||
var requestHandlers = config.RequestHandlers;
|
||||
|
||||
config.RequestHandlers = (c, e, od) =>
|
||||
{
|
||||
if (requestHandlers != null)
|
||||
requestHandlers(c, e, od); // Original request handler
|
||||
|
||||
var filterAttribute = od.Attributes.Where(a => typeof(FuncBasedFilterAttribute).IsAssignableFrom(a.GetType())).Cast<FuncBasedFilterAttribute>().ToList();
|
||||
|
||||
filterAttribute.ForEach(a => c.Add(new FuncBasedOperationHandler(a)));
|
||||
};
|
||||
|
||||
return config;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,13 +14,16 @@
|
|||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Security
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
||||
{
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
|
||||
internal abstract class FuncBasedFilterAttribute : Attribute
|
||||
public static class Constants
|
||||
{
|
||||
public abstract Func<HttpRequestMessage, bool> Filter { get; }
|
||||
public const string ErrorFilterExpressionCannotBeNull = "The filterExpression cannot be null.";
|
||||
public const string ErrorParameterApplicationIdCannotBeNull = "Parameter applicationId cannot be null.";
|
||||
public const string ErrorParameterConfigureParamCannotBeNull = "Parameter configure cannot be null";
|
||||
public const string ErrorParameterClientIdCannotBeNull = "Parameter clientId cannot be null.";
|
||||
public const string ErrorParameterEndpointCannotBeNull = "Parameter endpoint cannot be null.";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,33 +20,21 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
|||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Security.Principal;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Activation;
|
||||
using System.ServiceModel.Web;
|
||||
using System.Web;
|
||||
using ApplicationServer.Http.Dispatcher;
|
||||
using Properties;
|
||||
using System.Web.Http;
|
||||
|
||||
[ServiceContract]
|
||||
[ServiceBehavior(IncludeExceptionDetailInFaults = false)]
|
||||
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
|
||||
public class EndpointService
|
||||
public class EndpointController : ApiController
|
||||
{
|
||||
protected readonly IEndpointRepository Repository;
|
||||
private readonly Func<HttpRequestMessage, string> mapUsernameDelegate;
|
||||
private static TimeSpan defaultEndpointExpirationTime = TimeSpan.FromDays(30);
|
||||
|
||||
public EndpointService()
|
||||
: this(NotificationServiceContext.Current.Configuration.StorageProvider, NotificationServiceContext.Current.Configuration.MapUsername)
|
||||
{
|
||||
}
|
||||
|
||||
public EndpointService(IEndpointRepository repository)
|
||||
public EndpointController(IEndpointRepository repository)
|
||||
: this(repository, NotificationServiceContext.Current.Configuration.MapUsername)
|
||||
{
|
||||
}
|
||||
|
||||
public EndpointService(IEndpointRepository repository, Func<HttpRequestMessage, string> mapUsernameDelegate)
|
||||
public EndpointController(IEndpointRepository repository, Func<HttpRequestMessage, string> mapUsernameDelegate)
|
||||
{
|
||||
if (repository == null)
|
||||
throw new ArgumentNullException("repository");
|
||||
|
@ -55,8 +43,8 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
|||
this.mapUsernameDelegate = mapUsernameDelegate;
|
||||
}
|
||||
|
||||
[WebGet(UriTemplate = ""), AuthenticateEndpoint, AuthorizeManagementEndpoint]
|
||||
public IEnumerable<Endpoint> GetAll()
|
||||
[AuthenticateEndpoint, AuthorizeManagementEndpoint]
|
||||
public IEnumerable<Endpoint> Get()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -68,17 +56,17 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
|||
}
|
||||
}
|
||||
|
||||
[WebGet(UriTemplate = "{applicationId}/{deviceId}"), AuthenticateEndpoint, AuthorizeManagementEndpoint]
|
||||
public HttpResponseMessage<Endpoint> Get(string applicationId, string deviceId)
|
||||
[AuthenticateEndpoint, AuthorizeManagementEndpoint]
|
||||
public HttpResponseMessage<Endpoint> Get(string applicationId, string tileId, string clientId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var endpoint = this.Repository.Find(e => e.ApplicationId == applicationId && e.DeviceId == deviceId);
|
||||
var endpoint = this.Repository.Find(applicationId, tileId, clientId);
|
||||
|
||||
if (endpoint == null)
|
||||
return new HttpResponseMessage<Endpoint>(null, HttpStatusCode.NotFound);
|
||||
|
||||
return new HttpResponseMessage<Endpoint>(endpoint, HttpStatusCode.OK);
|
||||
return new HttpResponseMessage<Endpoint>(Endpoint.To<Endpoint>(endpoint), HttpStatusCode.OK);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
|
@ -86,43 +74,46 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
|||
}
|
||||
}
|
||||
|
||||
[WebInvoke(UriTemplate = "", Method = "PUT"), AuthenticateEndpoint, AuthorizeRegistrationEndpoint]
|
||||
public HttpResponseMessage<Endpoint> Put(HttpRequestMessage<Endpoint> message)
|
||||
[AuthenticateEndpoint, AuthorizeRegistrationEndpoint]
|
||||
public HttpResponseMessage<Endpoint> Put(Endpoint endpoint)
|
||||
{
|
||||
if (message == null)
|
||||
throw WebException(Resources.ErrorParameterEndpointCannotBeNull, HttpStatusCode.BadRequest);
|
||||
|
||||
try
|
||||
{
|
||||
var readTask = message.Content.ReadAsAsync();
|
||||
readTask.Wait();
|
||||
var endpoint = readTask.Result;
|
||||
if (endpoint == null)
|
||||
throw WebException(Constants.ErrorParameterEndpointCannotBeNull, HttpStatusCode.BadRequest);
|
||||
|
||||
// Set the username under which the app will store the channel
|
||||
endpoint.UserId = this.mapUsernameDelegate(message);
|
||||
endpoint.UserId = this.mapUsernameDelegate(this.Request);
|
||||
|
||||
if (endpoint.ExpirationTime == null || endpoint.ExpirationTime == DateTime.MinValue)
|
||||
endpoint.ExpirationTime = DateTime.UtcNow.Add(defaultEndpointExpirationTime);
|
||||
|
||||
this.Repository.InsertOrUpdate(endpoint);
|
||||
return new HttpResponseMessage<Endpoint>(endpoint, HttpStatusCode.Accepted);
|
||||
}
|
||||
catch (HttpResponseException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
throw WebException(exception.Message, HttpStatusCode.InternalServerError);
|
||||
}
|
||||
}
|
||||
|
||||
[WebInvoke(UriTemplate = "{applicationId}/{deviceId}", Method = "DELETE"), AuthenticateEndpoint, AuthorizeRegistrationEndpoint]
|
||||
public HttpResponseMessage Delete(string applicationId, string deviceId)
|
||||
[AuthenticateEndpoint, AuthorizeRegistrationEndpoint]
|
||||
public HttpResponseMessage Delete(string applicationId, string tileId, string clientId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(applicationId))
|
||||
throw WebException(Resources.ErrorParameterApplicationIdCannotBeNull, HttpStatusCode.BadRequest);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(deviceId))
|
||||
throw WebException(Resources.ErrorParameterDeviceIdCannotBeNull, HttpStatusCode.BadRequest);
|
||||
throw WebException(Constants.ErrorParameterApplicationIdCannotBeNull, HttpStatusCode.BadRequest);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(clientId))
|
||||
throw WebException(Constants.ErrorParameterClientIdCannotBeNull, HttpStatusCode.BadRequest);
|
||||
|
||||
try
|
||||
{
|
||||
this.Repository.Delete(applicationId, deviceId);
|
||||
return new HttpResponseMessage { StatusCode = HttpStatusCode.Accepted };
|
||||
this.Repository.Delete(applicationId, tileId, clientId);
|
||||
return new HttpResponseMessage(HttpStatusCode.Accepted);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
|
@ -19,45 +19,36 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http.Controllers;
|
||||
|
||||
public class NotificationServiceConfig
|
||||
{
|
||||
private Func<HttpRequestMessage, bool> authenticateRequest;
|
||||
private Func<HttpRequestMessage, bool> authorizeManagementRequest;
|
||||
private Func<HttpRequestMessage, bool> authorizeRegistrationRequest;
|
||||
private Func<HttpActionContext, bool> authenticateRequest;
|
||||
private Func<HttpActionContext, bool> authorizeManagementRequest;
|
||||
private Func<HttpActionContext, bool> authorizeRegistrationRequest;
|
||||
private Func<HttpRequestMessage, string> mapUsername;
|
||||
|
||||
public NotificationServiceConfig()
|
||||
{
|
||||
this.DelegatingHandlers = new Type[] { };
|
||||
this.DelegatingHandlers = new DelegatingHandler[] { };
|
||||
}
|
||||
|
||||
public Func<HttpRequestMessage, bool> AuthenticateRequest
|
||||
public Func<HttpActionContext, bool> AuthenticateRequest
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.authenticateRequest ?? (this.authenticateRequest = DefaultAnonymousAccess);
|
||||
}
|
||||
get { return this.authenticateRequest ?? (this.authenticateRequest = DefaultAnonymousAccess); }
|
||||
|
||||
set { this.authenticateRequest = value; }
|
||||
}
|
||||
|
||||
public Func<HttpRequestMessage, bool> AuthorizeManagementRequest
|
||||
public Func<HttpActionContext, bool> AuthorizeManagementRequest
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.authorizeManagementRequest ?? (this.authorizeManagementRequest = DefaultAnonymousAccess);
|
||||
}
|
||||
|
||||
get { return this.authorizeManagementRequest ?? (this.authorizeManagementRequest = DefaultAnonymousAccess); }
|
||||
set { this.authorizeManagementRequest = value; }
|
||||
}
|
||||
|
||||
public Func<HttpRequestMessage, bool> AuthorizeRegistrationRequest
|
||||
public Func<HttpActionContext, bool> AuthorizeRegistrationRequest
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.authorizeRegistrationRequest ?? (this.authorizeRegistrationRequest = DefaultAnonymousAccess);
|
||||
}
|
||||
get { return this.authorizeRegistrationRequest ?? (this.authorizeRegistrationRequest = DefaultAnonymousAccess); }
|
||||
|
||||
set { this.authorizeRegistrationRequest = value; }
|
||||
}
|
||||
|
@ -72,14 +63,17 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
|||
return this.mapUsername;
|
||||
}
|
||||
|
||||
set { this.mapUsername = value; }
|
||||
set
|
||||
{
|
||||
this.mapUsername = value;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Type> DelegatingHandlers { get; set; }
|
||||
public IEnumerable<DelegatingHandler> DelegatingHandlers { get; set; }
|
||||
|
||||
public IEndpointRepository StorageProvider { get; set; }
|
||||
|
||||
private static bool DefaultAnonymousAccess(HttpRequestMessage message)
|
||||
private static bool DefaultAnonymousAccess(HttpActionContext message)
|
||||
{
|
||||
// By default, return always true (anonymous user)
|
||||
return true;
|
||||
|
@ -91,4 +85,4 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
|||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,8 +18,6 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
|||
{
|
||||
using System;
|
||||
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Notifications.Properties;
|
||||
|
||||
public class NotificationServiceContext
|
||||
{
|
||||
private static readonly NotificationServiceContext Instance = new NotificationServiceContext();
|
||||
|
@ -39,9 +37,9 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
|||
public void Configure(Action<NotificationServiceConfig> configure)
|
||||
{
|
||||
if (configure == null)
|
||||
throw new ArgumentException(Resources.ErrorParameterConfigureParamCannotBeNull, "configure");
|
||||
|
||||
throw new ArgumentException(Constants.ErrorParameterConfigureParamCannotBeNull, "configure");
|
||||
|
||||
configure(this.config);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
// ----------------------------------------------------------------------------------
|
||||
// Microsoft Developer & Platform Evangelism
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ----------------------------------------------------------------------------------
|
||||
// The example companies, organizations, products, domain names,
|
||||
// e-mail addresses, logos, people, places, and events depicted
|
||||
// herein are fictitious. No association with any real company,
|
||||
// organization, product, domain name, email address, logo, person,
|
||||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.235
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.WindowsAzure.Samples.CloudServices.Notifications.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The filterExpression cannot be null..
|
||||
/// </summary>
|
||||
internal static string ErrorFilterExpressionCannotBeNull {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorFilterExpressionCannotBeNull", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Parameter applicationId cannot be null..
|
||||
/// </summary>
|
||||
internal static string ErrorParameterApplicationIdCannotBeNull {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorParameterApplicationIdCannotBeNull", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Parameter configure cannot be null.
|
||||
/// </summary>
|
||||
internal static string ErrorParameterConfigureParamCannotBeNull {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorParameterConfigureParamCannotBeNull", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Parameter deviceId cannot be null..
|
||||
/// </summary>
|
||||
internal static string ErrorParameterDeviceIdCannotBeNull {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorParameterDeviceIdCannotBeNull", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Parameter endpoint cannot be null..
|
||||
/// </summary>
|
||||
internal static string ErrorParameterEndpointCannotBeNull {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorParameterEndpointCannotBeNull", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="ErrorParameterApplicationIdCannotBeNull" xml:space="preserve">
|
||||
<value>Parameter applicationId cannot be null.</value>
|
||||
</data>
|
||||
<data name="ErrorParameterDeviceIdCannotBeNull" xml:space="preserve">
|
||||
<value>Parameter deviceId cannot be null.</value>
|
||||
</data>
|
||||
<data name="ErrorParameterEndpointCannotBeNull" xml:space="preserve">
|
||||
<value>Parameter endpoint cannot be null.</value>
|
||||
</data>
|
||||
<data name="ErrorFilterExpressionCannotBeNull" xml:space="preserve">
|
||||
<value>The filterExpression cannot be null.</value>
|
||||
</data>
|
||||
<data name="ErrorParameterConfigureParamCannotBeNull" xml:space="preserve">
|
||||
<value>Parameter configure cannot be null</value>
|
||||
</data>
|
||||
</root>
|
|
@ -16,10 +16,11 @@
|
|||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using System.Web.Routing;
|
||||
using ApplicationServer.Http;
|
||||
|
||||
public static class RouteExtensions
|
||||
{
|
||||
|
@ -30,11 +31,35 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
|||
routes.MapRegistrationServiceRoute(prefix, handlers);
|
||||
}
|
||||
|
||||
public static void MapRegistrationServiceRoute(this RouteCollection routes, string prefix, params Type[] handlers)
|
||||
public static void MapRegistrationServiceRoute(this RouteCollection routes, string prefix, params DelegatingHandler[] handlers)
|
||||
{
|
||||
var configuration = new HttpConfiguration().AddDelegatingHandlers(handlers).AddRequestHandlers();
|
||||
var currentConfiguration = GlobalConfiguration.Configuration;
|
||||
|
||||
routes.MapServiceRoute<EndpointService>(prefix, configuration);
|
||||
// Handlers
|
||||
currentConfiguration.AddDelegatingHandlers(handlers);
|
||||
|
||||
// Register Dependencies
|
||||
// NOTE: For any types that your dependency resolver does not handle,
|
||||
// GetService should return null and GetServices should return an empty collection object
|
||||
currentConfiguration.ServiceResolver.SetResolver(
|
||||
t =>
|
||||
{
|
||||
if (t == typeof(EndpointController))
|
||||
{
|
||||
return new EndpointController(
|
||||
NotificationServiceContext.Current.Configuration.StorageProvider,
|
||||
NotificationServiceContext.Current.Configuration.MapUsername);
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
t => new List<object>());
|
||||
|
||||
// Routes
|
||||
routes.MapHttpRoute(
|
||||
name: prefix,
|
||||
routeTemplate: prefix + "/{applicationId}/{clientId}/{tileId}",
|
||||
defaults: new { Controller = "Endpoint", applicationId = RouteParameter.Optional, tileId = RouteParameter.Optional, clientId = RouteParameter.Optional });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,14 +17,13 @@
|
|||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
||||
{
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http.Controllers;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
|
||||
internal sealed class AuthenticateEndpointAttribute : FuncBasedFilterAttribute
|
||||
internal sealed class AuthenticateEndpointAttribute : FuncBasedAuthorizationFilterAttribute
|
||||
{
|
||||
public override Func<HttpRequestMessage, bool> Filter
|
||||
public override Func<HttpActionContext, bool> Filter
|
||||
{
|
||||
get { return NotificationServiceContext.Current.Configuration.AuthenticateRequest; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,14 +17,13 @@
|
|||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
||||
{
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http.Controllers;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
|
||||
internal sealed class AuthorizeManagementEndpointAttribute : FuncBasedFilterAttribute
|
||||
internal sealed class AuthorizeManagementEndpointAttribute : FuncBasedAuthorizationFilterAttribute
|
||||
{
|
||||
public override Func<HttpRequestMessage, bool> Filter
|
||||
public override Func<HttpActionContext, bool> Filter
|
||||
{
|
||||
get { return NotificationServiceContext.Current.Configuration.AuthorizeManagementRequest; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,12 +17,11 @@
|
|||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
||||
{
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http.Controllers;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
|
||||
internal sealed class AuthorizeRegistrationEndpointAttribute : FuncBasedFilterAttribute
|
||||
internal sealed class AuthorizeRegistrationEndpointAttribute : FuncBasedAuthorizationFilterAttribute
|
||||
{
|
||||
public override Func<HttpRequestMessage, bool> Filter
|
||||
public override Func<HttpActionContext, bool> Filter
|
||||
{
|
||||
get { return NotificationServiceContext.Current.Configuration.AuthorizeRegistrationRequest; }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
// ----------------------------------------------------------------------------------
|
||||
// Microsoft Developer & Platform Evangelism
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ----------------------------------------------------------------------------------
|
||||
// The example companies, organizations, products, domain names,
|
||||
// e-mail addresses, logos, people, places, and events depicted
|
||||
// herein are fictitious. No association with any real company,
|
||||
// organization, product, domain name, email address, logo, person,
|
||||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications
|
||||
{
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Web;
|
||||
using System.Web.Http;
|
||||
using System.Web.Http.Controllers;
|
||||
using System.Web.Http.Filters;
|
||||
|
||||
internal abstract class FuncBasedAuthorizationFilterAttribute : AuthorizationFilterAttribute
|
||||
{
|
||||
public abstract Func<HttpActionContext, bool> Filter { get; }
|
||||
|
||||
public override void OnAuthorization(HttpActionContext actionContext)
|
||||
{
|
||||
if (this.Filter(actionContext))
|
||||
{
|
||||
base.OnAuthorization(actionContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
// HACK: Prevent ASP.NET Forms Authentication to redirect the user to the login page.
|
||||
// This thread-safe approach adds a header with the suppression to be read on the
|
||||
// OnEndRequest event of the pipelien. In order to fully support the supression you should have the ASP.NET Module
|
||||
// that does this (SuppressFormsAuthenticationRedirectModule).
|
||||
var response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
||||
response.Headers.Add(SuppressFormsAuthenticationRedirectModule.SuppressFormsHeaderName, "true");
|
||||
|
||||
throw new HttpResponseException(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,271 +0,0 @@
|
|||
<StyleCopSettings Version="105">
|
||||
<GlobalSettings>
|
||||
<StringProperty Name="MergeSettingsFiles">NoMerge</StringProperty>
|
||||
</GlobalSettings>
|
||||
<Parsers>
|
||||
<Parser ParserId="StyleCop.CSharp.CsParser">
|
||||
<ParserSettings>
|
||||
<BooleanProperty Name="AnalyzeDesignerFiles">False</BooleanProperty>
|
||||
<CollectionProperty Name="GeneratedFileFilters">
|
||||
<Value>\.g\.cs$</Value>
|
||||
<Value>\.generated\.cs$</Value>
|
||||
<Value>\.g\.i\.cs$</Value>
|
||||
</CollectionProperty>
|
||||
</ParserSettings>
|
||||
</Parser>
|
||||
</Parsers>
|
||||
<Analyzers>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.NamingRules">
|
||||
<AnalyzerSettings>
|
||||
<CollectionProperty Name="Hungarian">
|
||||
<Value>as</Value>
|
||||
<Value>do</Value>
|
||||
<Value>id</Value>
|
||||
<Value>if</Value>
|
||||
<Value>in</Value>
|
||||
<Value>is</Value>
|
||||
<Value>my</Value>
|
||||
<Value>no</Value>
|
||||
<Value>on</Value>
|
||||
<Value>to</Value>
|
||||
<Value>ui</Value>
|
||||
</CollectionProperty>
|
||||
</AnalyzerSettings>
|
||||
</Analyzer>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules">
|
||||
<Rules>
|
||||
<Rule Name="ElementsMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PartialElementsMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="EnumerationItemsMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationMustContainValidXml">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustHaveSummary">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PartialElementDocumentationMustHaveSummary">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustHaveSummaryText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PartialElementDocumentationMustHaveSummaryText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustNotHaveDefaultSummary">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParametersMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParameterDocumentationMustMatchElementParameters">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParameterDocumentationMustDeclareParameterName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParameterDocumentationMustHaveText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementReturnValueMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementReturnValueDocumentationMustHaveText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="VoidReturnValueMustNotBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParametersMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParametersMustBeDocumentedPartialClass">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParameterDocumentationMustMatchTypeParameters">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParameterDocumentationMustDeclareParameterName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParameterDocumentationMustHaveText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PropertySummaryDocumentationMustMatchAccessors">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PropertySummaryDocumentationMustOmitSetAccessorWithRestrictedAccess">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustNotBeCopiedAndPasted">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="SingleLineCommentsMustNotUseDocumentationStyleSlashes">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationTextMustNotBeEmpty">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationTextMustContainWhitespace">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationMustMeetCharacterPercentage">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationTextMustMeetMinimumCharacterLength">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ConstructorSummaryDocumentationMustBeginWithStandardText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DestructorSummaryDocumentationMustBeginWithStandardText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationHeadersMustNotContainBlankLines">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="IncludedDocumentationXPathDoesNotExist">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="IncludeNodeDoesNotContainValidFileAndPath">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileMustHaveHeader">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustShowCopyright">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustHaveCopyrightText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustContainFileName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderFileNameDocumentationMustMatchFileName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustHaveValidCompanyText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
</Rules>
|
||||
<AnalyzerSettings />
|
||||
</Analyzer>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.LayoutRules">
|
||||
<Rules>
|
||||
<Rule Name="CurlyBracketsForMultiLineStatementsMustNotShareLine">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="StatementMustNotBeOnSingleLine">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementMustNotBeOnSingleLine">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="CurlyBracketsMustNotBeOmitted">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="AllAccessorsMustBeMultiLineOrSingleLine">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
</Rules>
|
||||
<AnalyzerSettings />
|
||||
</Analyzer>
|
||||
</Analyzers>
|
||||
</StyleCopSettings>
|
|
@ -27,4 +27,4 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications.WindowsAzur
|
|||
&& ((DataServiceClientException)ex.InnerException).StatusCode == 404;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,13 +17,22 @@
|
|||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications.WindowsAzure
|
||||
{
|
||||
using System;
|
||||
using System.Data.Services.Common;
|
||||
using System.Data.Services.Common;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Microsoft.WindowsAzure.Samples.Common.Storage;
|
||||
|
||||
|
||||
[DataServiceEntity]
|
||||
[DataServiceKey(new[] { "PartitionKey", "RowKey" })]
|
||||
public class EndpointTableRow : Endpoint, ITableServiceEntity
|
||||
{
|
||||
private string rowKey;
|
||||
|
||||
public EndpointTableRow()
|
||||
{
|
||||
this.rowKey = string.Empty;
|
||||
}
|
||||
|
||||
public string PartitionKey
|
||||
{
|
||||
get { return this.ApplicationId; }
|
||||
|
@ -32,10 +41,28 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications.WindowsAzur
|
|||
|
||||
public string RowKey
|
||||
{
|
||||
get { return this.DeviceId; }
|
||||
set { this.DeviceId = value; }
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(this.rowKey))
|
||||
this.RowKey = CreateRowKey(this.TileId, this.ClientId);
|
||||
|
||||
return this.rowKey;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.rowKey = value;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual DateTime Timestamp { get; set; }
|
||||
|
||||
public static string CreateRowKey(string tileId, string clientId)
|
||||
{
|
||||
var encodedTileId = Convert.ToBase64String(Encoding.UTF8.GetBytes(tileId ?? string.Empty)).Replace("/", "%");
|
||||
var encodedClientId = Convert.ToBase64String(Encoding.UTF8.GetBytes(clientId ?? string.Empty)).Replace("/", "%");
|
||||
|
||||
return string.Format(CultureInfo.InvariantCulture, "{0}_{1}", encodedTileId, encodedClientId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,11 +20,12 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications.WindowsAzur
|
|||
using System.Collections.Generic;
|
||||
using System.Data.Services.Client;
|
||||
using System.Linq;
|
||||
using Common.Storage;
|
||||
using Microsoft.WindowsAzure;
|
||||
using Microsoft.WindowsAzure.Samples.Common.Storage;
|
||||
|
||||
public class WindowsAzureEndpointRepository : IEndpointRepository
|
||||
{
|
||||
protected readonly IAzureTable<EndpointTableRow> Table;
|
||||
protected readonly IAzureTable<EndpointTableRow> Table;
|
||||
|
||||
private const string EndpointsTableName = "Endpoints";
|
||||
|
||||
|
@ -77,6 +78,26 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications.WindowsAzur
|
|||
return this.Endpoints.Where(filterExpression).ToList().FirstOrDefault();
|
||||
}
|
||||
|
||||
public Endpoint Find(string applicationId, string tileId, string clientId)
|
||||
{
|
||||
var rowkey = EndpointTableRow.CreateRowKey(tileId, clientId);
|
||||
Endpoint endpoint = null;
|
||||
|
||||
try
|
||||
{
|
||||
endpoint = this.Endpoints.Where(e => e.PartitionKey.Equals(applicationId) && e.RowKey.Equals(rowkey)).ToList().FirstOrDefault();
|
||||
}
|
||||
catch (DataServiceQueryException e)
|
||||
{
|
||||
if (e.Response.StatusCode != 404)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
public void InsertOrUpdate(Endpoint endpoint)
|
||||
{
|
||||
if (endpoint == null)
|
||||
|
@ -85,15 +106,15 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Notifications.WindowsAzur
|
|||
this.Table.AddOrUpdateEntity(Endpoint.To<EndpointTableRow>(endpoint));
|
||||
}
|
||||
|
||||
public void Delete(string applicationId, string deviceId)
|
||||
public void Delete(string applicationId, string tileId, string clientId)
|
||||
{
|
||||
if (applicationId == null)
|
||||
if (string.IsNullOrWhiteSpace(applicationId))
|
||||
throw new ArgumentNullException("applicationId");
|
||||
|
||||
if (deviceId == null)
|
||||
throw new ArgumentNullException("deviceId");
|
||||
if (string.IsNullOrWhiteSpace(clientId))
|
||||
throw new ArgumentNullException("clientId");
|
||||
|
||||
var storedEndpoint = this.Find(e => e.ApplicationId.Equals(applicationId) && e.DeviceId.Equals(deviceId));
|
||||
var storedEndpoint = this.Find(applicationId, tileId, clientId);
|
||||
|
||||
if (storedEndpoint != null)
|
||||
this.Table.DeleteEntity(Endpoint.To<EndpointTableRow>(storedEndpoint));
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="aspnet.suppressformsredirect" version="0.0.1.4" />
|
||||
<package id="HttpClient" version="0.6.0" />
|
||||
<package id="JsonValue" version="0.6.0" />
|
||||
<package id="WebApi" version="0.6.0" />
|
||||
<package id="WebApi.All" version="0.6.0" />
|
||||
<package id="WebApi.Enhancements" version="0.6.0" />
|
||||
<package id="WebApi.OData" version="0.6.0" />
|
||||
<package id="AspNetWebApi" version="4.0.20126.16343" />
|
||||
<package id="AspNetWebApi.Core" version="4.0.20126.16343" />
|
||||
<package id="System.Json" version="4.0.20126.16343" />
|
||||
<package id="System.Net.Http" version="2.0.20126.16343" />
|
||||
<package id="System.Net.Http.Formatting" version="4.0.20126.16343" />
|
||||
<package id="System.Web.Http.Common" version="4.0.20126.16343" />
|
||||
</packages>
|
|
@ -12,6 +12,7 @@
|
|||
<AssemblyName>WindowsAzure.Storage.Proxy</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -35,51 +36,43 @@
|
|||
<Reference Include="AspNet.SuppressFormsRedirect">
|
||||
<HintPath>..\packages\aspnet.suppressformsredirect.0.0.1.4\lib\40\AspNet.SuppressFormsRedirect.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="EntityDataModel">
|
||||
<HintPath>..\packages\WebApi.OData.0.6.0\lib\40-Full\EntityDataModel.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ApplicationServer.Http">
|
||||
<HintPath>..\packages\WebApi.0.6.0\lib\40-Full\Microsoft.ApplicationServer.Http.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ApplicationServer.HttpEnhancements">
|
||||
<HintPath>..\packages\WebApi.Enhancements.0.6.0\lib\40-Full\Microsoft.ApplicationServer.HttpEnhancements.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Data.Spatial">
|
||||
<HintPath>..\packages\WebApi.OData.0.6.0\lib\40-Full\Microsoft.Data.Spatial.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Json">
|
||||
<HintPath>..\packages\JsonValue.0.6.0\lib\40\Microsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Net.Http.Formatting">
|
||||
<HintPath>..\packages\HttpClient.0.6.0\lib\40\Microsoft.Net.Http.Formatting.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Net.Http.Formatting.OData">
|
||||
<HintPath>..\packages\WebApi.OData.0.6.0\lib\40-Full\Microsoft.Net.Http.Formatting.OData.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Runtime.Serialization.Internal">
|
||||
<HintPath>..\packages\WebApi.0.6.0\lib\40-Full\Microsoft.Runtime.Serialization.Internal.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Server.Common">
|
||||
<HintPath>..\packages\WebApi.0.6.0\lib\40-Full\Microsoft.Server.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ServiceModel.Internal">
|
||||
<HintPath>..\packages\WebApi.0.6.0\lib\40-Full\Microsoft.ServiceModel.Internal.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.WindowsAzure.StorageClient, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.OData">
|
||||
<HintPath>..\packages\WebApi.OData.0.6.0\lib\40-Full\System.Data.OData.dll</HintPath>
|
||||
<Reference Include="System.Json, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Json.4.0.20126.16343\lib\net40\System.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http">
|
||||
<HintPath>..\packages\HttpClient.0.6.0\lib\40\System.Net.Http.dll</HintPath>
|
||||
<Reference Include="System.Net.Http, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Net.Http.2.0.20126.16343\lib\net40\System.Net.Http.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Net.Http.Formatting.4.0.20126.16343\lib\net40\System.Net.Http.Formatting.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.WebRequest, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Net.Http.2.0.20126.16343\lib\net40\System.Net.Http.WebRequest.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.ServiceModel.Activation" />
|
||||
<Reference Include="System.ServiceModel.Web" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\AspNetWebApi.Core.4.0.20126.16343\lib\net40\System.Web.Http.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Http.Common, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\System.Web.Http.Common.4.0.20126.16343\lib\net40\System.Web.Http.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Http.WebHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\AspNetWebApi.4.0.20126.16343\lib\net40\System.Web.Http.WebHost.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
|
@ -88,24 +81,21 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ConfigurationExtensions.cs" />
|
||||
<Compile Include="Constants.cs" />
|
||||
<Compile Include="Handlers\ContentTypeSanitizerMessageHandler.cs" />
|
||||
<Compile Include="Handlers\ControllerFilteredMessageProcessingHandler.cs" />
|
||||
<Compile Include="GlobalSuppressions.cs" />
|
||||
<Compile Include="Helpers\CanonicalizedString.cs" />
|
||||
<Compile Include="Helpers\CredentialExtensions.cs" />
|
||||
<Compile Include="Helpers\BlobExtensions.cs" />
|
||||
<Compile Include="Properties\Resource.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resource.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="QueuesProxyService.cs" />
|
||||
<Compile Include="Controllers\QueuesProxyController.cs" />
|
||||
<Compile Include="RouteExtensions.cs" />
|
||||
<Compile Include="SasCloudBlobContainerProperties.cs" />
|
||||
<Compile Include="Security\AuthorizeTablesAccessAttribute.cs" />
|
||||
<Compile Include="Security\AuthorizeQueuesAccessAttribute.cs" />
|
||||
<Compile Include="Security\AuthorizeBlobsAccessAttribute.cs" />
|
||||
<Compile Include="Security\FuncBasedFilterAttribute.cs" />
|
||||
<Compile Include="Security\FuncBasedOperationHandler.cs" />
|
||||
<Compile Include="TablesProxyService.cs" />
|
||||
<Compile Include="Security\FuncBasedAuthorizationFilterAttribute.cs" />
|
||||
<Compile Include="Controllers\TablesProxyController.cs" />
|
||||
<Compile Include="Helpers\Extensions.cs" />
|
||||
<Compile Include="Handlers\AzureQueuesProxyHandler.cs" />
|
||||
<Compile Include="Handlers\AzureTablesProxyHandler.cs" />
|
||||
|
@ -114,23 +104,15 @@
|
|||
<Compile Include="SasCloudBlobContainerListResponse.cs" />
|
||||
<Compile Include="StorageServicesConfig.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SharedAccessSignatureService.cs" />
|
||||
<Compile Include="Controllers\SharedAccessSignatureController.cs" />
|
||||
<Compile Include="StorageServicesContext.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Properties\Resource.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resource.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>$(ProjectDir)..\NuGet\NuGet.exe install $(ProjectDir)packages.config -OutputDirectory $(ProjectDir)..\packages\</PreBuildEvent>
|
||||
<PreBuildEvent>$(ProjectDir)..\.nuget\NuGet.exe install $(ProjectDir)packages.config -OutputDirectory $(ProjectDir)..\packages\</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<!-- 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.
|
||||
|
|
|
@ -16,36 +16,17 @@
|
|||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
||||
{
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.ApplicationServer.Http;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Security;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
|
||||
internal static class ConfigurationExtensions
|
||||
{
|
||||
internal static HttpConfiguration AddDelegatingHandlers(this HttpConfiguration config, params Type[] handlers)
|
||||
internal static HttpConfiguration AddDelegatingHandlers(this HttpConfiguration config, params DelegatingHandler[] handlers)
|
||||
{
|
||||
handlers.ToList().ForEach(t => config.MessageHandlers.Add(t));
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
internal static HttpConfiguration AddRequestHandlers(this HttpConfiguration config)
|
||||
{
|
||||
var requestHandlers = config.RequestHandlers;
|
||||
|
||||
config.RequestHandlers = (c, e, od) =>
|
||||
{
|
||||
if (requestHandlers != null)
|
||||
requestHandlers(c, e, od); // Original request handler
|
||||
|
||||
var filterAttribute = od.Attributes.Where(a => typeof(FuncBasedFilterAttribute).IsAssignableFrom(a.GetType())).Cast<FuncBasedFilterAttribute>().ToList();
|
||||
|
||||
filterAttribute.ForEach(a => c.Add(new FuncBasedOperationHandler(a)));
|
||||
};
|
||||
|
||||
return config;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
// ----------------------------------------------------------------------------------
|
||||
// Microsoft Developer & Platform Evangelism
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ----------------------------------------------------------------------------------
|
||||
// The example companies, organizations, products, domain names,
|
||||
// e-mail addresses, logos, people, places, and events depicted
|
||||
// herein are fictitious. No association with any real company,
|
||||
// organization, product, domain name, email address, logo, person,
|
||||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
||||
{
|
||||
public class Constants
|
||||
{
|
||||
public const string CloudStorageAccountNullArgumentErrorMessage = "The Storage Account setting cannot be null.";
|
||||
|
||||
public const string CompMustBeSasArgumentErrorMessage = "Argument comp must be sas for this operation.";
|
||||
|
||||
public const string ConfigureActionArgumentNullErrorMessage = "Parameter configureAction cannot be null.";
|
||||
|
||||
public const string ContainerCannotBeNullErrorMessage = "Container can not be null.";
|
||||
|
||||
public const string ContainerNameNullArgumentErrorMessage = "The containerName cannot be null.";
|
||||
|
||||
public const string HttpClientDisposedErrorString = "The connection with Windows Azure has been closed before the result could be read.";
|
||||
|
||||
public const string InvalidPublicAccessModeArgumentErrorMessage = "Container Access Mode is invalid.";
|
||||
|
||||
public const string PublicAccessNotSpecifiedErrorMessage = "You have specified an ACL operation but not sent the required HTTP header.";
|
||||
|
||||
public const string RequestCannotBeNullErrorMessage = "Request can not be null.";
|
||||
|
||||
public const string RequestNullErrorMessage = "Called service with null HttpRequestMessage.";
|
||||
|
||||
public const string ResponseNullArgumentErrorString = "Response can not be null.";
|
||||
|
||||
public const string WindowsAzureStorageExceptionStringMessage = "There was an error when sending data to Windows Azure Storage.";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
// ----------------------------------------------------------------------------------
|
||||
// Microsoft Developer & Platform Evangelism
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ----------------------------------------------------------------------------------
|
||||
// The example companies, organizations, products, domain names,
|
||||
// e-mail addresses, logos, people, places, and events depicted
|
||||
// herein are fictitious. No association with any real company,
|
||||
// organization, product, domain name, email address, logo, person,
|
||||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
||||
{
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Handlers;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Helpers;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Security;
|
||||
|
||||
public class QueuesProxyController : ApiController
|
||||
{
|
||||
private static readonly AzureQueuesProxyHandler Proxy = new AzureQueuesProxyHandler();
|
||||
|
||||
[AuthorizeQueuesAccess, CLSCompliant(false)]
|
||||
public HttpResponseMessage Post([FromUri]string path)
|
||||
{
|
||||
if (this.Request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Constants.RequestCannotBeNullErrorMessage, Constants.RequestCannotBeNullErrorMessage);
|
||||
|
||||
this.Request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path ?? string.Empty;
|
||||
return Proxy.ProcessRequest(this.Request);
|
||||
}
|
||||
|
||||
[AuthorizeQueuesAccess, CLSCompliant(false)]
|
||||
public HttpResponseMessage Put([FromUri]string path)
|
||||
{
|
||||
if (this.Request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Constants.RequestCannotBeNullErrorMessage, Constants.RequestCannotBeNullErrorMessage);
|
||||
|
||||
this.Request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path ?? string.Empty;
|
||||
return Proxy.ProcessRequest(this.Request);
|
||||
}
|
||||
|
||||
[AuthorizeQueuesAccess, CLSCompliant(false)]
|
||||
public HttpResponseMessage Get(string path)
|
||||
{
|
||||
if (this.Request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Constants.RequestCannotBeNullErrorMessage, Constants.RequestCannotBeNullErrorMessage);
|
||||
|
||||
this.Request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path ?? string.Empty;
|
||||
return Proxy.ProcessRequest(this.Request);
|
||||
}
|
||||
|
||||
[AuthorizeQueuesAccess, CLSCompliant(false)]
|
||||
public HttpResponseMessage Delete(string path)
|
||||
{
|
||||
if (this.Request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Constants.RequestCannotBeNullErrorMessage, Constants.RequestCannotBeNullErrorMessage);
|
||||
|
||||
this.Request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path ?? string.Empty;
|
||||
return Proxy.ProcessRequest(this.Request);
|
||||
}
|
||||
|
||||
[AuthorizeQueuesAccess, CLSCompliant(false)]
|
||||
[AcceptVerbs("HEAD")]
|
||||
public HttpResponseMessage Head(string path)
|
||||
{
|
||||
if (this.Request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Constants.RequestCannotBeNullErrorMessage, Constants.RequestCannotBeNullErrorMessage);
|
||||
|
||||
this.Request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path ?? string.Empty;
|
||||
return Proxy.ProcessRequest(this.Request);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,20 +22,14 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
|||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Activation;
|
||||
using System.ServiceModel.Web;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.ApplicationServer.Http.Dispatcher;
|
||||
using System.Web.Http;
|
||||
using Microsoft.WindowsAzure;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Helpers;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Properties;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Security;
|
||||
using Microsoft.WindowsAzure.StorageClient;
|
||||
|
||||
[ServiceContract]
|
||||
[ServiceBehavior(IncludeExceptionDetailInFaults = false)]
|
||||
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
|
||||
public class SharedAccessSignatureService
|
||||
public class SharedAccessSignatureController : ApiController
|
||||
{
|
||||
private const SharedAccessPermissions ContainerSharedAccessPermissions = SharedAccessPermissions.Write | SharedAccessPermissions.Delete | SharedAccessPermissions.List | SharedAccessPermissions.Read;
|
||||
|
||||
|
@ -45,48 +39,43 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
|||
|
||||
private readonly CloudBlobClient cloudBlobClient;
|
||||
|
||||
public SharedAccessSignatureService()
|
||||
public SharedAccessSignatureController()
|
||||
: this(StorageServicesContext.Current.Configuration.CloudStorageAccount)
|
||||
{
|
||||
}
|
||||
|
||||
public SharedAccessSignatureService(CloudStorageAccount storageAccount)
|
||||
public SharedAccessSignatureController(CloudStorageAccount storageAccount)
|
||||
{
|
||||
if (storageAccount == null)
|
||||
throw new ArgumentNullException("storageAccount", Resource.CloudStorageAccountNullArgumentErrorMessage);
|
||||
throw new ArgumentNullException("storageAccount", Constants.CloudStorageAccountNullArgumentErrorMessage);
|
||||
|
||||
this.cloudBlobClient = storageAccount.CreateCloudBlobClient();
|
||||
}
|
||||
|
||||
[OperationContract]
|
||||
[AuthorizeBlobsAccess]
|
||||
[CLSCompliant(false)]
|
||||
[WebInvoke(Method = "PUT", UriTemplate = "/containers/{containerName}?comp={operation}")]
|
||||
public HttpResponseMessage CreateContainer(HttpRequestMessage request, string containerName, string operation)
|
||||
public HttpResponseMessage Put(string containerName, string comp)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException("request", Resource.RequestNullErrorMessage);
|
||||
|
||||
// Determine if the public-access header was sent
|
||||
string publicAccessMode = GetPublicAccessMode(request);
|
||||
string publicAccessMode = GetPublicAccessMode(this.Request);
|
||||
|
||||
// operation is ACL but headers have not been sent
|
||||
if (string.IsNullOrEmpty(publicAccessMode) && !string.IsNullOrEmpty(operation) && operation.Equals("acl", StringComparison.OrdinalIgnoreCase))
|
||||
if (string.IsNullOrEmpty(publicAccessMode) && !string.IsNullOrEmpty(comp) && comp.Equals("acl", StringComparison.OrdinalIgnoreCase))
|
||||
publicAccessMode = "OFF";
|
||||
|
||||
// operation is null and container name is null
|
||||
if (string.IsNullOrWhiteSpace(containerName) && string.IsNullOrWhiteSpace(operation))
|
||||
throw WebException(Resource.ContainerNameNullArgumentErrorMessage, HttpStatusCode.BadRequest);
|
||||
if (string.IsNullOrWhiteSpace(containerName) && string.IsNullOrWhiteSpace(comp))
|
||||
throw WebException(Constants.ContainerNameNullArgumentErrorMessage, HttpStatusCode.BadRequest);
|
||||
|
||||
try
|
||||
{
|
||||
var responseStatusCode = HttpStatusCode.InternalServerError;
|
||||
var container = this.cloudBlobClient.GetContainerReference(containerName);
|
||||
|
||||
UpdateContainerWithMetadataFromRequest(request, container);
|
||||
UpdateContainerWithMetadataFromRequest(this.Request, container);
|
||||
|
||||
// operation is null --> the create container mode is requested
|
||||
if (string.IsNullOrEmpty(operation))
|
||||
if (string.IsNullOrEmpty(comp))
|
||||
{
|
||||
responseStatusCode = HttpStatusCode.Created;
|
||||
container.Create();
|
||||
|
@ -103,7 +92,7 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
|||
}
|
||||
|
||||
// operation == metadata
|
||||
if (!string.IsNullOrEmpty(operation) && operation.Equals("metadata", StringComparison.OrdinalIgnoreCase))
|
||||
if (!string.IsNullOrEmpty(comp) && comp.Equals("metadata", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
responseStatusCode = HttpStatusCode.OK;
|
||||
container.SetMetadata();
|
||||
|
@ -117,11 +106,9 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
|||
}
|
||||
}
|
||||
|
||||
[OperationContract]
|
||||
[AuthorizeBlobsAccess]
|
||||
[CLSCompliant(false)]
|
||||
[WebInvoke(Method = "DELETE", UriTemplate = "/containers/{containerName}")]
|
||||
public HttpResponseMessage DeleteContainer(string containerName)
|
||||
public HttpResponseMessage Delete(string containerName)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -136,10 +123,9 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
|||
}
|
||||
}
|
||||
|
||||
[OperationContract]
|
||||
[AuthorizeBlobsAccess]
|
||||
[CLSCompliant(false)]
|
||||
[WebInvoke(Method = "HEAD", UriTemplate = "/containers/{containerName}")]
|
||||
[AcceptVerbs("HEAD")]
|
||||
public HttpResponseMessage GetContainerProperties(string containerName)
|
||||
{
|
||||
try
|
||||
|
@ -165,17 +151,23 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
|||
}
|
||||
}
|
||||
|
||||
[OperationContract]
|
||||
[AuthorizeBlobsAccess]
|
||||
[CLSCompliant(false)]
|
||||
[WebGet(UriTemplate = "/containers?prefix={containerPrefix}")]
|
||||
public HttpResponseMessage<SasCloudBlobContainerListResponse> ListContainers(string containerPrefix)
|
||||
public HttpResponseMessage<SasCloudBlobContainerListResponse> GetContainers()
|
||||
{
|
||||
return this.GetContainers(string.Empty);
|
||||
}
|
||||
|
||||
[AuthorizeBlobsAccess]
|
||||
[CLSCompliant(false)]
|
||||
public HttpResponseMessage<SasCloudBlobContainerListResponse> GetContainers(string prefix)
|
||||
{
|
||||
IEnumerable<CloudBlobContainer> containers;
|
||||
if (!string.IsNullOrEmpty(containerPrefix))
|
||||
|
||||
if (!string.IsNullOrEmpty(prefix))
|
||||
{
|
||||
containerPrefix = containerPrefix.TrimStart('/', '\\').Replace('\\', '/');
|
||||
containers = this.cloudBlobClient.ListContainers(containerPrefix);
|
||||
prefix = prefix.TrimStart('/', '\\').Replace('\\', '/');
|
||||
containers = this.cloudBlobClient.ListContainers(prefix);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -193,14 +185,12 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
|||
return new HttpResponseMessage<SasCloudBlobContainerListResponse>(result, HttpStatusCode.OK);
|
||||
}
|
||||
|
||||
[OperationContract]
|
||||
[AuthorizeBlobsAccess]
|
||||
[CLSCompliant(false)]
|
||||
[WebGet(UriTemplate = "/containers/{containerName}?comp={operation}")]
|
||||
public HttpResponseMessage GetContainerSharedAccessSignature(string containerName, string operation)
|
||||
public HttpResponseMessage GetContainerSharedAccessSignature(string containerName, string comp)
|
||||
{
|
||||
if (string.IsNullOrEmpty(operation) || !operation.Equals("sas", StringComparison.OrdinalIgnoreCase))
|
||||
throw WebException(Resource.CompMustBeSasArgumentErrorMessage, HttpStatusCode.BadRequest);
|
||||
if (string.IsNullOrEmpty(comp) || !comp.Equals("sas", StringComparison.OrdinalIgnoreCase))
|
||||
throw WebException(Constants.CompMustBeSasArgumentErrorMessage, HttpStatusCode.BadRequest);
|
||||
|
||||
var container = this.cloudBlobClient.GetContainerReference(containerName);
|
||||
var sas = container.GetSharedAccessSignature(new SharedAccessPolicy
|
||||
|
@ -213,14 +203,12 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
|||
return new HttpResponseMessage { Content = new StringContent(uriBuilder.Uri.AbsoluteUri), StatusCode = HttpStatusCode.OK };
|
||||
}
|
||||
|
||||
[OperationContract]
|
||||
[AuthorizeBlobsAccess]
|
||||
[CLSCompliant(false)]
|
||||
[WebGet(UriTemplate = "/blobs/{containerName}/{*blobName}?comp={operation}")]
|
||||
public HttpResponseMessage GetBlobSharedAccessSignature(string containerName, string blobName, string operation)
|
||||
public HttpResponseMessage GetBlobSharedAccessSignature(string containerName, string blobName, string comp)
|
||||
{
|
||||
if (string.IsNullOrEmpty(operation) || !operation.Equals("sas", StringComparison.OrdinalIgnoreCase))
|
||||
throw WebException(Resource.CompMustBeSasArgumentErrorMessage, HttpStatusCode.BadRequest);
|
||||
if (string.IsNullOrEmpty(comp) || !comp.Equals("sas", StringComparison.OrdinalIgnoreCase))
|
||||
throw WebException(Constants.CompMustBeSasArgumentErrorMessage, HttpStatusCode.BadRequest);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -314,4 +302,4 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
|||
return publicAccessMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
// ----------------------------------------------------------------------------------
|
||||
// Microsoft Developer & Platform Evangelism
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ----------------------------------------------------------------------------------
|
||||
// The example companies, organizations, products, domain names,
|
||||
// e-mail addresses, logos, people, places, and events depicted
|
||||
// herein are fictitious. No association with any real company,
|
||||
// organization, product, domain name, email address, logo, person,
|
||||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
||||
{
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Handlers;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Helpers;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Security;
|
||||
|
||||
public class TablesProxyController : ApiController
|
||||
{
|
||||
private static readonly AzureTablesProxyHandler Proxy = new AzureTablesProxyHandler();
|
||||
|
||||
[AuthorizeTablesAccess, CLSCompliant(false)]
|
||||
public HttpResponseMessage Post([FromUri]string path)
|
||||
{
|
||||
if (this.Request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Constants.RequestCannotBeNullErrorMessage, Constants.RequestCannotBeNullErrorMessage);
|
||||
|
||||
this.Request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path ?? string.Empty;
|
||||
return Proxy.ProcessRequest(this.Request);
|
||||
}
|
||||
|
||||
[AuthorizeTablesAccess, CLSCompliant(false)]
|
||||
public HttpResponseMessage Put([FromUri]string path)
|
||||
{
|
||||
if (this.Request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Constants.RequestCannotBeNullErrorMessage, Constants.RequestCannotBeNullErrorMessage);
|
||||
|
||||
this.Request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path ?? string.Empty;
|
||||
return Proxy.ProcessRequest(this.Request);
|
||||
}
|
||||
|
||||
[AuthorizeTablesAccess, CLSCompliant(false)]
|
||||
public HttpResponseMessage Get(string path)
|
||||
{
|
||||
if (this.Request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Constants.RequestCannotBeNullErrorMessage, Constants.RequestCannotBeNullErrorMessage);
|
||||
|
||||
this.Request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path ?? string.Empty;
|
||||
return Proxy.ProcessRequest(this.Request);
|
||||
}
|
||||
|
||||
[AuthorizeTablesAccess, CLSCompliant(false)]
|
||||
public HttpResponseMessage Delete(string path)
|
||||
{
|
||||
if (this.Request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Constants.RequestCannotBeNullErrorMessage, Constants.RequestCannotBeNullErrorMessage);
|
||||
|
||||
this.Request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path ?? string.Empty;
|
||||
return Proxy.ProcessRequest(this.Request);
|
||||
}
|
||||
|
||||
[AuthorizeTablesAccess, CLSCompliant(false)]
|
||||
[AcceptVerbs("MERGE")]
|
||||
public HttpResponseMessage Merge([FromUri]string path)
|
||||
{
|
||||
if (this.Request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Constants.RequestCannotBeNullErrorMessage, Constants.RequestCannotBeNullErrorMessage);
|
||||
|
||||
this.Request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path ?? string.Empty;
|
||||
return Proxy.ProcessRequest(this.Request);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
// ----------------------------------------------------------------------------------
|
||||
// Microsoft Developer & Platform Evangelism
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ----------------------------------------------------------------------------------
|
||||
// The example companies, organizations, products, domain names,
|
||||
// e-mail addresses, logos, people, places, and events depicted
|
||||
// herein are fictitious. No association with any real company,
|
||||
// organization, product, domain name, email address, logo, person,
|
||||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Handlers
|
||||
{
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading;
|
||||
|
||||
public class ContentTypeSanitizerMessageHandler : ControllerFilteredMessageProcessingHandler
|
||||
{
|
||||
protected override HttpRequestMessage ProcessRequestHandler(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
if (request.Content.Headers.ContentType == null)
|
||||
{
|
||||
// Set the default Content-Type when it is not specified
|
||||
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/xml");
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
// ----------------------------------------------------------------------------------
|
||||
// Microsoft Developer & Platform Evangelism
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ----------------------------------------------------------------------------------
|
||||
// The example companies, organizations, products, domain names,
|
||||
// e-mail addresses, logos, people, places, and events depicted
|
||||
// herein are fictitious. No association with any real company,
|
||||
// organization, product, domain name, email address, logo, person,
|
||||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Handlers
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Web.Http;
|
||||
|
||||
public abstract class ControllerFilteredMessageProcessingHandler : MessageProcessingHandler
|
||||
{
|
||||
public IList<string> ConfiguredControllers { get; set; }
|
||||
|
||||
protected abstract HttpRequestMessage ProcessRequestHandler(HttpRequestMessage request, CancellationToken cancellationToken);
|
||||
|
||||
protected override HttpRequestMessage ProcessRequest(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
var routeData = request.GetRouteData();
|
||||
var controllerName = routeData.Values.ContainsKey("controller") ?
|
||||
routeData.Values["controller"].ToString() :
|
||||
string.Empty;
|
||||
|
||||
if (this.ConfiguredControllers == null ||
|
||||
this.ConfiguredControllers.Any(c => c.Equals(controllerName, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return this.ProcessRequestHandler(request, cancellationToken);
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
protected override HttpResponseMessage ProcessResponse(HttpResponseMessage response, CancellationToken cancellationToken)
|
||||
{
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,7 +26,6 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Handlers
|
|||
using System.Web;
|
||||
using Microsoft.WindowsAzure;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Helpers;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Properties;
|
||||
|
||||
public abstract class StorageProxyHandler
|
||||
{
|
||||
|
@ -47,7 +46,7 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Handlers
|
|||
public HttpResponseMessage ProcessRequest(HttpRequestMessage request)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException("request", Resource.RequestCannotBeNullErrorMessage);
|
||||
throw new ArgumentNullException("request", Constants.RequestCannotBeNullErrorMessage);
|
||||
|
||||
var originalUri = request.RequestUri;
|
||||
|
||||
|
@ -79,7 +78,7 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Handlers
|
|||
protected string GetAzureStorageRequestBody(string proxyRequestBody, HttpRequestMessage request)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException("request", Resource.RequestCannotBeNullErrorMessage);
|
||||
throw new ArgumentNullException("request", Constants.RequestCannotBeNullErrorMessage);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(proxyRequestBody))
|
||||
{
|
||||
|
@ -111,7 +110,6 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Handlers
|
|||
return azureStorageResponseBody.Replace(oldValue, newValue);
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
protected abstract void SignRequest(HttpRequestMessage request);
|
||||
|
||||
private static string GetLocalPath(Uri originalUri, Uri mappedUri, HttpRequestMessage request)
|
||||
|
@ -167,18 +165,18 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Handlers
|
|||
{
|
||||
var task = azureClient.SendAsync(request);
|
||||
|
||||
// Synchronize Azure Invokation
|
||||
// Synchronize Azure Invocation
|
||||
task.Wait();
|
||||
|
||||
return task.Result;
|
||||
}
|
||||
catch (HttpException webException)
|
||||
{
|
||||
throw Extensions.StorageException(HttpStatusCode.InternalServerError, Resource.WindowsAzureStorageExceptionStringMessage, webException.Message);
|
||||
throw Extensions.StorageException(HttpStatusCode.InternalServerError, Constants.WindowsAzureStorageExceptionStringMessage, webException.Message);
|
||||
}
|
||||
catch (ObjectDisposedException exception)
|
||||
{
|
||||
throw Extensions.StorageException(HttpStatusCode.InternalServerError, Resource.HttpClientDisposedErrorString, exception.Message);
|
||||
throw Extensions.StorageException(HttpStatusCode.InternalServerError, Constants.HttpClientDisposedErrorString, exception.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,15 +17,14 @@
|
|||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Helpers
|
||||
{
|
||||
using System;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Properties;
|
||||
|
||||
public static class BlobExtensions
|
||||
{
|
||||
public static SasCloudBlobContainer ToModel(this StorageClient.CloudBlobContainer container)
|
||||
public static SasCloudBlobContainer ToModel(this Microsoft.WindowsAzure.StorageClient.CloudBlobContainer container)
|
||||
{
|
||||
if (container == null)
|
||||
{
|
||||
throw new ArgumentNullException("container", Resource.ContainerCannotBeNullErrorMessage);
|
||||
throw new ArgumentNullException("container", Constants.ContainerCannotBeNullErrorMessage);
|
||||
}
|
||||
|
||||
return new SasCloudBlobContainer
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Helpers
|
|||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using Microsoft.WindowsAzure;
|
||||
|
||||
internal static class CredentialExtensions
|
||||
{
|
||||
|
@ -74,7 +75,7 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Helpers
|
|||
canonicalizedString.AppendCanonicalizedElement("0");
|
||||
else
|
||||
{
|
||||
canonicalizedString.AppendCanonicalizedElement(string.Empty);
|
||||
canonicalizedString.AppendCanonicalizedElement(string.Empty);
|
||||
}
|
||||
|
||||
canonicalizedString.AppendCanonicalizedElement(string.Empty);
|
||||
|
@ -179,7 +180,7 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Helpers
|
|||
{
|
||||
var canonicalizedString = new CanonicalizedString(string.Empty);
|
||||
|
||||
var keyList =
|
||||
var keyList =
|
||||
headers.Where(h => h.Key.StartsWith("x-ms-", StringComparison.OrdinalIgnoreCase)).Select(header => header.Key).ToList();
|
||||
|
||||
keyList.Sort();
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Helpers
|
|||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using Microsoft.ApplicationServer.Http.Dispatcher;
|
||||
using System.Web.Http;
|
||||
|
||||
public static class Extensions
|
||||
{
|
||||
|
@ -54,7 +54,8 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Helpers
|
|||
response.ReasonPhrase = error;
|
||||
response.Content = new StringContent(errorMessage);
|
||||
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/atom+xml");
|
||||
|
||||
return new HttpResponseException(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,187 +0,0 @@
|
|||
// ----------------------------------------------------------------------------------
|
||||
// Microsoft Developer & Platform Evangelism
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ----------------------------------------------------------------------------------
|
||||
// The example companies, organizations, products, domain names,
|
||||
// e-mail addresses, logos, people, places, and events depicted
|
||||
// herein are fictitious. No association with any real company,
|
||||
// organization, product, domain name, email address, logo, person,
|
||||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.235
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resource {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resource() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.WindowsAzure.Samples.CloudServices.Storage.Properties.Resource", typeof(Resource).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The Storage Account setting cannot be null.
|
||||
/// </summary>
|
||||
internal static string CloudStorageAccountNullArgumentErrorMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("CloudStorageAccountNullArgumentErrorMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Argument comp must be sas for this operation.
|
||||
/// </summary>
|
||||
internal static string CompMustBeSasArgumentErrorMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("CompMustBeSasArgumentErrorMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Parameter configureAction cannot be null.
|
||||
/// </summary>
|
||||
internal static string ConfigureActionArgumentNullErrorMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("ConfigureActionArgumentNullErrorMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Container can not be null..
|
||||
/// </summary>
|
||||
internal static string ContainerCannotBeNullErrorMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("ContainerCannotBeNullErrorMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The containerName cannot be null..
|
||||
/// </summary>
|
||||
internal static string ContainerNameNullArgumentErrorMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("ContainerNameNullArgumentErrorMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The connection with Windows Azure has been closed before the result could be read.
|
||||
/// </summary>
|
||||
internal static string HttpClientDisposedErrorString {
|
||||
get {
|
||||
return ResourceManager.GetString("HttpClientDisposedErrorString", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Container Access Mode is invalid.
|
||||
/// </summary>
|
||||
internal static string InvalidPublicAccessModeArgumentErrorMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("InvalidPublicAccessModeArgumentErrorMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to You have specified an ACL operation but not sent the required HTTP header.
|
||||
/// </summary>
|
||||
internal static string PublicAccessNotSpecifiedErrorMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("PublicAccessNotSpecifiedErrorMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Request can not be null..
|
||||
/// </summary>
|
||||
internal static string RequestCannotBeNullErrorMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("RequestCannotBeNullErrorMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Called service with null HttpRequestMessage.
|
||||
/// </summary>
|
||||
internal static string RequestNullErrorMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("RequestNullErrorMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Response can not be null..
|
||||
/// </summary>
|
||||
internal static string ResponseNullArgumentErrorString {
|
||||
get {
|
||||
return ResourceManager.GetString("ResponseNullArgumentErrorString", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to There was an error when sending data to Windows Azure Storage.
|
||||
/// </summary>
|
||||
internal static string WindowsAzureStorageExceptionStringMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("WindowsAzureStorageExceptionStringMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="CloudStorageAccountNullArgumentErrorMessage" xml:space="preserve">
|
||||
<value>The Storage Account setting cannot be null</value>
|
||||
</data>
|
||||
<data name="ContainerNameNullArgumentErrorMessage" xml:space="preserve">
|
||||
<value>The containerName cannot be null.</value>
|
||||
</data>
|
||||
<data name="CompMustBeSasArgumentErrorMessage" xml:space="preserve">
|
||||
<value>Argument comp must be sas for this operation</value>
|
||||
</data>
|
||||
<data name="PublicAccessNotSpecifiedErrorMessage" xml:space="preserve">
|
||||
<value>You have specified an ACL operation but not sent the required HTTP header</value>
|
||||
</data>
|
||||
<data name="RequestNullErrorMessage" xml:space="preserve">
|
||||
<value>Called service with null HttpRequestMessage</value>
|
||||
</data>
|
||||
<data name="InvalidPublicAccessModeArgumentErrorMessage" xml:space="preserve">
|
||||
<value>Container Access Mode is invalid</value>
|
||||
</data>
|
||||
<data name="ConfigureActionArgumentNullErrorMessage" xml:space="preserve">
|
||||
<value>Parameter configureAction cannot be null</value>
|
||||
</data>
|
||||
<data name="RequestCannotBeNullErrorMessage" xml:space="preserve">
|
||||
<value>Request can not be null.</value>
|
||||
</data>
|
||||
<data name="ResponseNullArgumentErrorString" xml:space="preserve">
|
||||
<value>Response can not be null.</value>
|
||||
</data>
|
||||
<data name="ContainerCannotBeNullErrorMessage" xml:space="preserve">
|
||||
<value>Container can not be null.</value>
|
||||
</data>
|
||||
<data name="WindowsAzureStorageExceptionStringMessage" xml:space="preserve">
|
||||
<value>There was an error when sending data to Windows Azure Storage</value>
|
||||
</data>
|
||||
<data name="HttpClientDisposedErrorString" xml:space="preserve">
|
||||
<value>The connection with Windows Azure has been closed before the result could be read</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1,87 +0,0 @@
|
|||
// ----------------------------------------------------------------------------------
|
||||
// Microsoft Developer & Platform Evangelism
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ----------------------------------------------------------------------------------
|
||||
// The example companies, organizations, products, domain names,
|
||||
// e-mail addresses, logos, people, places, and events depicted
|
||||
// herein are fictitious. No association with any real company,
|
||||
// organization, product, domain name, email address, logo, person,
|
||||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
||||
{
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Activation;
|
||||
using System.ServiceModel.Web;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Handlers;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Helpers;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Properties;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Security;
|
||||
|
||||
[ServiceContract]
|
||||
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
|
||||
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
|
||||
public class QueuesProxyService
|
||||
{
|
||||
private static readonly AzureQueuesProxyHandler Proxy = new AzureQueuesProxyHandler();
|
||||
|
||||
[WebInvoke(Method = "POST", UriTemplate = "{*path}"), OperationContract, AuthorizeQueuesAccess, CLSCompliant(false)]
|
||||
public HttpResponseMessage HandlePost(HttpRequestMessage request, string path)
|
||||
{
|
||||
if (request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Resource.RequestCannotBeNullErrorMessage, Resource.RequestCannotBeNullErrorMessage);
|
||||
|
||||
request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path;
|
||||
return Proxy.ProcessRequest(request);
|
||||
}
|
||||
|
||||
[WebInvoke(Method = "PUT", UriTemplate = "{*path}"), OperationContract, AuthorizeQueuesAccess, CLSCompliant(false)]
|
||||
public HttpResponseMessage HandlePut(HttpRequestMessage request, string path)
|
||||
{
|
||||
if (request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Resource.RequestCannotBeNullErrorMessage, Resource.RequestCannotBeNullErrorMessage);
|
||||
|
||||
request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path;
|
||||
return Proxy.ProcessRequest(request);
|
||||
}
|
||||
|
||||
[WebInvoke(Method = "GET", UriTemplate = "{*path}"), OperationContract, AuthorizeQueuesAccess, CLSCompliant(false)]
|
||||
public HttpResponseMessage HandleGet(HttpRequestMessage request, string path)
|
||||
{
|
||||
if (request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Resource.RequestCannotBeNullErrorMessage, Resource.RequestCannotBeNullErrorMessage);
|
||||
|
||||
request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path;
|
||||
return Proxy.ProcessRequest(request);
|
||||
}
|
||||
|
||||
[WebInvoke(Method = "DELETE", UriTemplate = "{*path}"), OperationContract, AuthorizeQueuesAccess, CLSCompliant(false)]
|
||||
public HttpResponseMessage HandleDelete(HttpRequestMessage request, string path)
|
||||
{
|
||||
if (request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Resource.RequestCannotBeNullErrorMessage, Resource.RequestCannotBeNullErrorMessage);
|
||||
|
||||
request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path;
|
||||
return Proxy.ProcessRequest(request);
|
||||
}
|
||||
|
||||
[WebInvoke(Method = "HEAD", UriTemplate = "{*path}"), OperationContract, AuthorizeQueuesAccess, CLSCompliant(false)]
|
||||
public HttpResponseMessage HandleMerge(HttpRequestMessage request, string path)
|
||||
{
|
||||
if (request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Resource.RequestCannotBeNullErrorMessage, Resource.RequestCannotBeNullErrorMessage);
|
||||
|
||||
request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path;
|
||||
return Proxy.ProcessRequest(request);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,53 +16,87 @@
|
|||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
||||
{
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Web.Http;
|
||||
using System.Web.Routing;
|
||||
using Microsoft.ApplicationServer.Http;
|
||||
|
||||
public static class RouteExtensions
|
||||
{
|
||||
public static void MapQueuesProxyServiceRoute(this RouteCollection routes, string prefix)
|
||||
{
|
||||
var handlers = StorageServicesContext.Current.Configuration.DelegatingHandlers.ToArray();
|
||||
|
||||
routes.MapQueuesProxyServiceRoute(prefix, handlers);
|
||||
routes.MapQueuesProxyServiceRoute(prefix, new DelegatingHandler[] { });
|
||||
}
|
||||
|
||||
public static void MapQueuesProxyServiceRoute(this RouteCollection routes, string prefix, params Type[] handlers)
|
||||
public static void MapQueuesProxyServiceRoute(this RouteCollection routes, string prefix, params DelegatingHandler[] handlers)
|
||||
{
|
||||
var configuration = new HttpConfiguration().AddDelegatingHandlers(handlers).AddRequestHandlers();
|
||||
var currentConfiguration = GlobalConfiguration.Configuration;
|
||||
|
||||
routes.MapServiceRoute<QueuesProxyService>(prefix, configuration);
|
||||
// Handlers
|
||||
currentConfiguration.AddDelegatingHandlers(handlers)
|
||||
.AddDelegatingHandlers(
|
||||
new[]
|
||||
{
|
||||
new Handlers.ContentTypeSanitizerMessageHandler { ConfiguredControllers = new[] { "QueuesProxy" } }
|
||||
});
|
||||
|
||||
// Routes
|
||||
routes.MapHttpRoute(
|
||||
name: prefix,
|
||||
routeTemplate: prefix + "/{*path}",
|
||||
defaults: new { Controller = "QueuesProxy", path = RouteParameter.Optional });
|
||||
}
|
||||
|
||||
public static void MapTablesProxyServiceRoute(this RouteCollection routes, string prefix)
|
||||
{
|
||||
var handlers = StorageServicesContext.Current.Configuration.DelegatingHandlers.ToArray();
|
||||
|
||||
routes.MapTablesProxyServiceRoute(prefix, handlers);
|
||||
routes.MapTablesProxyServiceRoute(prefix, new DelegatingHandler[] { });
|
||||
}
|
||||
|
||||
public static void MapTablesProxyServiceRoute(this RouteCollection routes, string prefix, params Type[] handlers)
|
||||
public static void MapTablesProxyServiceRoute(this RouteCollection routes, string prefix, params DelegatingHandler[] handlers)
|
||||
{
|
||||
var configuration = new HttpConfiguration().AddDelegatingHandlers(handlers).AddRequestHandlers();
|
||||
var currentConfiguration = GlobalConfiguration.Configuration;
|
||||
|
||||
routes.MapServiceRoute<TablesProxyService>(prefix, configuration);
|
||||
// Formatters
|
||||
currentConfiguration.Formatters.XmlFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/atom+xml"));
|
||||
|
||||
// Handlers
|
||||
currentConfiguration.AddDelegatingHandlers(handlers);
|
||||
|
||||
// Routes
|
||||
routes.MapHttpRoute(
|
||||
name: prefix,
|
||||
routeTemplate: prefix + "/{*path}",
|
||||
defaults: new { Controller = "TablesProxy", path = RouteParameter.Optional });
|
||||
}
|
||||
|
||||
public static void MapSasServiceRoute(this RouteCollection routes, string prefix)
|
||||
{
|
||||
var handlers = StorageServicesContext.Current.Configuration.DelegatingHandlers.ToArray();
|
||||
|
||||
routes.MapSasServiceRoute(prefix, handlers);
|
||||
routes.MapSasServiceRoute(prefix, new DelegatingHandler[] { });
|
||||
}
|
||||
|
||||
public static void MapSasServiceRoute(this RouteCollection routes, string prefix, params Type[] handlers)
|
||||
public static void MapSasServiceRoute(this RouteCollection routes, string prefix, params DelegatingHandler[] handlers)
|
||||
{
|
||||
var configuration = new HttpConfiguration().AddDelegatingHandlers(handlers).AddRequestHandlers();
|
||||
var currentConfiguration = GlobalConfiguration.Configuration;
|
||||
|
||||
routes.MapServiceRoute<SharedAccessSignatureService>(prefix, configuration);
|
||||
// Handlers
|
||||
currentConfiguration.AddDelegatingHandlers(handlers);
|
||||
|
||||
// Routes
|
||||
routes.MapHttpRoute(
|
||||
name: prefix + "_Containers",
|
||||
routeTemplate: prefix + "/containers",
|
||||
defaults: new { Controller = "SharedAccessSignature" });
|
||||
|
||||
routes.MapHttpRoute(
|
||||
name: prefix + "_Container",
|
||||
routeTemplate: prefix + "/containers/{containerName}",
|
||||
defaults: new { Controller = "SharedAccessSignature", containerName = RouteParameter.Optional });
|
||||
|
||||
routes.MapHttpRoute(
|
||||
name: prefix + "_Blob",
|
||||
routeTemplate: prefix + "/blobs/{containerName}/{*blobName}",
|
||||
defaults: new { Controller = "SharedAccessSignature" });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,13 +18,14 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Security
|
|||
{
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http.Controllers;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
|
||||
internal sealed class AuthorizeBlobsAccessAttribute : FuncBasedFilterAttribute
|
||||
internal sealed class AuthorizeBlobsAccessAttribute : FuncBasedAuthorizationFilterAttribute
|
||||
{
|
||||
public override Func<HttpRequestMessage, bool> Filter
|
||||
public override Func<HttpActionContext, bool> Filter
|
||||
{
|
||||
get { return StorageServicesContext.Current.Configuration.AuthorizeBlobsAccess; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,13 +18,14 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Security
|
|||
{
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http.Controllers;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
|
||||
internal sealed class AuthorizeQueuesAccessAttribute : FuncBasedFilterAttribute
|
||||
internal sealed class AuthorizeQueuesAccessAttribute : FuncBasedAuthorizationFilterAttribute
|
||||
{
|
||||
public override Func<HttpRequestMessage, bool> Filter
|
||||
public override Func<HttpActionContext, bool> Filter
|
||||
{
|
||||
get { return StorageServicesContext.Current.Configuration.AuthorizeQueuesAccess; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,13 +18,14 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Security
|
|||
{
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http.Controllers;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
|
||||
internal sealed class AuthorizeTablesAccessAttribute : FuncBasedFilterAttribute
|
||||
internal sealed class AuthorizeTablesAccessAttribute : FuncBasedAuthorizationFilterAttribute
|
||||
{
|
||||
public override Func<HttpRequestMessage, bool> Filter
|
||||
public override Func<HttpActionContext, bool> Filter
|
||||
{
|
||||
get { return StorageServicesContext.Current.Configuration.AuthorizeTablesAccess; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
// ----------------------------------------------------------------------------------
|
||||
// Microsoft Developer & Platform Evangelism
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ----------------------------------------------------------------------------------
|
||||
// The example companies, organizations, products, domain names,
|
||||
// e-mail addresses, logos, people, places, and events depicted
|
||||
// herein are fictitious. No association with any real company,
|
||||
// organization, product, domain name, email address, logo, person,
|
||||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Security
|
||||
{
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Web;
|
||||
using System.Web.Http;
|
||||
using System.Web.Http.Controllers;
|
||||
using System.Web.Http.Filters;
|
||||
|
||||
internal abstract class FuncBasedAuthorizationFilterAttribute : AuthorizationFilterAttribute
|
||||
{
|
||||
public abstract Func<HttpActionContext, bool> Filter { get; }
|
||||
|
||||
public override void OnAuthorization(HttpActionContext actionContext)
|
||||
{
|
||||
if (this.Filter(actionContext))
|
||||
{
|
||||
base.OnAuthorization(actionContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
// HACK: Prevent ASP.NET Forms Authentication to redirect the user to the login page.
|
||||
// This thread-safe approach adds a header with the suppression to be read on the
|
||||
// OnEndRequest event of the pipelien. In order to fully support the supression you should have the ASP.NET Module
|
||||
// that does this (SuppressFormsAuthenticationRedirectModule).
|
||||
var response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
||||
response.Headers.Add(SuppressFormsAuthenticationRedirectModule.SuppressFormsHeaderName, "true");
|
||||
|
||||
throw new HttpResponseException(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
// ----------------------------------------------------------------------------------
|
||||
// Microsoft Developer & Platform Evangelism
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ----------------------------------------------------------------------------------
|
||||
// The example companies, organizations, products, domain names,
|
||||
// e-mail addresses, logos, people, places, and events depicted
|
||||
// herein are fictitious. No association with any real company,
|
||||
// organization, product, domain name, email address, logo, person,
|
||||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage.Security
|
||||
{
|
||||
using System.Net.Http;
|
||||
using System.Web;
|
||||
using Microsoft.ApplicationServer.Http.Dispatcher;
|
||||
|
||||
internal class FuncBasedOperationHandler : HttpOperationHandler<HttpRequestMessage, HttpRequestMessage>
|
||||
{
|
||||
private readonly FuncBasedFilterAttribute filterAttribute;
|
||||
|
||||
public FuncBasedOperationHandler(FuncBasedFilterAttribute filterAttribute)
|
||||
: base("response")
|
||||
{
|
||||
this.filterAttribute = filterAttribute;
|
||||
}
|
||||
|
||||
protected override HttpRequestMessage OnHandle(HttpRequestMessage input)
|
||||
{
|
||||
if (this.filterAttribute.Filter(input))
|
||||
return input;
|
||||
|
||||
// HACK: Prevent ASP.NET Forms Authentication to redirect the user to the login page.
|
||||
// This thread-safe approach adds a header with the suppression to be read on the
|
||||
// OnEndRequest event of the pipelien. In order to fully support the supression you should have the ASP.NET Module
|
||||
// that does this (SuppressFormsAuthenticationRedirectModule).
|
||||
var response = new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
|
||||
response.Headers.Add(SuppressFormsAuthenticationRedirectModule.SuppressFormsHeaderName, "true");
|
||||
|
||||
throw new HttpResponseException(response);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,271 +0,0 @@
|
|||
<StyleCopSettings Version="105">
|
||||
<GlobalSettings>
|
||||
<StringProperty Name="MergeSettingsFiles">NoMerge</StringProperty>
|
||||
</GlobalSettings>
|
||||
<Parsers>
|
||||
<Parser ParserId="StyleCop.CSharp.CsParser">
|
||||
<ParserSettings>
|
||||
<BooleanProperty Name="AnalyzeDesignerFiles">False</BooleanProperty>
|
||||
<CollectionProperty Name="GeneratedFileFilters">
|
||||
<Value>\.g\.cs$</Value>
|
||||
<Value>\.generated\.cs$</Value>
|
||||
<Value>\.g\.i\.cs$</Value>
|
||||
</CollectionProperty>
|
||||
</ParserSettings>
|
||||
</Parser>
|
||||
</Parsers>
|
||||
<Analyzers>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.NamingRules">
|
||||
<AnalyzerSettings>
|
||||
<CollectionProperty Name="Hungarian">
|
||||
<Value>as</Value>
|
||||
<Value>do</Value>
|
||||
<Value>id</Value>
|
||||
<Value>if</Value>
|
||||
<Value>in</Value>
|
||||
<Value>is</Value>
|
||||
<Value>my</Value>
|
||||
<Value>no</Value>
|
||||
<Value>on</Value>
|
||||
<Value>to</Value>
|
||||
<Value>ui</Value>
|
||||
</CollectionProperty>
|
||||
</AnalyzerSettings>
|
||||
</Analyzer>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules">
|
||||
<Rules>
|
||||
<Rule Name="ElementsMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PartialElementsMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="EnumerationItemsMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationMustContainValidXml">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustHaveSummary">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PartialElementDocumentationMustHaveSummary">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustHaveSummaryText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PartialElementDocumentationMustHaveSummaryText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustNotHaveDefaultSummary">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParametersMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParameterDocumentationMustMatchElementParameters">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParameterDocumentationMustDeclareParameterName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParameterDocumentationMustHaveText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementReturnValueMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementReturnValueDocumentationMustHaveText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="VoidReturnValueMustNotBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParametersMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParametersMustBeDocumentedPartialClass">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParameterDocumentationMustMatchTypeParameters">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParameterDocumentationMustDeclareParameterName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParameterDocumentationMustHaveText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PropertySummaryDocumentationMustMatchAccessors">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PropertySummaryDocumentationMustOmitSetAccessorWithRestrictedAccess">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustNotBeCopiedAndPasted">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="SingleLineCommentsMustNotUseDocumentationStyleSlashes">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationTextMustNotBeEmpty">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationTextMustContainWhitespace">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationMustMeetCharacterPercentage">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationTextMustMeetMinimumCharacterLength">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ConstructorSummaryDocumentationMustBeginWithStandardText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DestructorSummaryDocumentationMustBeginWithStandardText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationHeadersMustNotContainBlankLines">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="IncludedDocumentationXPathDoesNotExist">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="IncludeNodeDoesNotContainValidFileAndPath">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileMustHaveHeader">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustShowCopyright">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustHaveCopyrightText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustContainFileName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderFileNameDocumentationMustMatchFileName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustHaveValidCompanyText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
</Rules>
|
||||
<AnalyzerSettings />
|
||||
</Analyzer>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.LayoutRules">
|
||||
<Rules>
|
||||
<Rule Name="CurlyBracketsForMultiLineStatementsMustNotShareLine">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="StatementMustNotBeOnSingleLine">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementMustNotBeOnSingleLine">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="CurlyBracketsMustNotBeOmitted">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="AllAccessorsMustBeMultiLineOrSingleLine">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
</Rules>
|
||||
<AnalyzerSettings />
|
||||
</Analyzer>
|
||||
</Analyzers>
|
||||
</StyleCopSettings>
|
|
@ -18,18 +18,23 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
|||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using System.Web.Http.Controllers;
|
||||
using Microsoft.WindowsAzure;
|
||||
|
||||
public class StorageServicesConfig
|
||||
{
|
||||
private const int DefaultMaximmumResponseSize = 1024 * 1024;
|
||||
private const int DefaultSasExpirationSize = 15;
|
||||
|
||||
private Func<HttpRequestMessage, bool> authorizeQueuesAccess;
|
||||
private Func<HttpRequestMessage, bool> authorizeTablesAccess;
|
||||
private Func<HttpRequestMessage, bool> authorizeBlobsAccess;
|
||||
private Func<HttpRequestMessage, bool> authenticateRequest;
|
||||
private Func<HttpActionContext, bool> authorizeQueuesAccess;
|
||||
private Func<HttpActionContext, bool> authorizeTablesAccess;
|
||||
private Func<HttpActionContext, bool> authorizeBlobsAccess;
|
||||
private Func<HttpActionContext, bool> authenticateRequest;
|
||||
private Func<HttpRequestMessage, string> mapUserName;
|
||||
private IEnumerable<DelegatingHandler> delegatingHandlers;
|
||||
|
||||
private int containerSasExpirationTime;
|
||||
private int blobsSasExpirationTime;
|
||||
|
@ -37,7 +42,7 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
|||
|
||||
public StorageServicesConfig()
|
||||
{
|
||||
this.DelegatingHandlers = new Type[] { };
|
||||
this.delegatingHandlers = new DelegatingHandler[] { };
|
||||
}
|
||||
|
||||
public CloudStorageAccount CloudStorageAccount { get; set; }
|
||||
|
@ -90,7 +95,7 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
|||
}
|
||||
}
|
||||
|
||||
public Func<HttpRequestMessage, bool> AuthorizeTablesAccess
|
||||
public Func<HttpActionContext, bool> AuthorizeTablesAccess
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -100,7 +105,7 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
|||
set { this.authorizeTablesAccess = value; }
|
||||
}
|
||||
|
||||
public Func<HttpRequestMessage, bool> AuthorizeQueuesAccess
|
||||
public Func<HttpActionContext, bool> AuthorizeQueuesAccess
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -110,7 +115,7 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
|||
set { this.authorizeQueuesAccess = value; }
|
||||
}
|
||||
|
||||
public Func<HttpRequestMessage, bool> AuthorizeBlobsAccess
|
||||
public Func<HttpActionContext, bool> AuthorizeBlobsAccess
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -120,7 +125,7 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
|||
set { this.authorizeBlobsAccess = value; }
|
||||
}
|
||||
|
||||
public Func<HttpRequestMessage, bool> AuthenticateRequest
|
||||
public Func<HttpActionContext, bool> AuthenticateRequest
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -146,9 +151,21 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
|||
set { this.mapUserName = value; }
|
||||
}
|
||||
|
||||
public IEnumerable<Type> DelegatingHandlers { get; set; }
|
||||
public IEnumerable<DelegatingHandler> DelegatingHandlers
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.delegatingHandlers;
|
||||
}
|
||||
|
||||
private static bool DefaultAnonymousAccess(HttpRequestMessage message)
|
||||
set
|
||||
{
|
||||
this.delegatingHandlers = value;
|
||||
GlobalConfiguration.Configuration.AddDelegatingHandlers(value.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
private static bool DefaultAnonymousAccess(HttpActionContext message)
|
||||
{
|
||||
// By default, return always true (anonymous user)
|
||||
return true;
|
||||
|
@ -160,4 +177,4 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
|||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,8 +18,6 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
|||
{
|
||||
using System;
|
||||
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Properties;
|
||||
|
||||
public class StorageServicesContext
|
||||
{
|
||||
private static readonly StorageServicesContext Instance = new StorageServicesContext();
|
||||
|
@ -39,7 +37,7 @@ namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
|||
public void Configure(Action<StorageServicesConfig> configureAction)
|
||||
{
|
||||
if (configureAction == null)
|
||||
throw new ArgumentException(Resource.ConfigureActionArgumentNullErrorMessage, "configureAction");
|
||||
throw new ArgumentException(Constants.ConfigureActionArgumentNullErrorMessage, "configureAction");
|
||||
|
||||
configureAction(this.config);
|
||||
}
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
// ----------------------------------------------------------------------------------
|
||||
// Microsoft Developer & Platform Evangelism
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ----------------------------------------------------------------------------------
|
||||
// The example companies, organizations, products, domain names,
|
||||
// e-mail addresses, logos, people, places, and events depicted
|
||||
// herein are fictitious. No association with any real company,
|
||||
// organization, product, domain name, email address, logo, person,
|
||||
// places, or events is intended or should be inferred.
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.WindowsAzure.Samples.CloudServices.Storage
|
||||
{
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Activation;
|
||||
using System.ServiceModel.Web;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Handlers;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Helpers;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Properties;
|
||||
using Microsoft.WindowsAzure.Samples.CloudServices.Storage.Security;
|
||||
|
||||
[ServiceContract]
|
||||
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
|
||||
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
|
||||
public class TablesProxyService
|
||||
{
|
||||
private static readonly AzureTablesProxyHandler Proxy = new AzureTablesProxyHandler();
|
||||
|
||||
[WebInvoke(Method = "POST", UriTemplate = "{*path}"), OperationContract, AuthorizeTablesAccess, CLSCompliant(false)]
|
||||
public HttpResponseMessage HandlePost(HttpRequestMessage request, string path)
|
||||
{
|
||||
if (request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Resource.RequestCannotBeNullErrorMessage, Resource.RequestCannotBeNullErrorMessage);
|
||||
|
||||
request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path;
|
||||
return Proxy.ProcessRequest(request);
|
||||
}
|
||||
|
||||
[WebInvoke(Method = "PUT", UriTemplate = "{*path}"), OperationContract, AuthorizeTablesAccess, CLSCompliant(false)]
|
||||
public HttpResponseMessage HandlePut(HttpRequestMessage request, string path)
|
||||
{
|
||||
if (request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Resource.RequestCannotBeNullErrorMessage, Resource.RequestCannotBeNullErrorMessage);
|
||||
|
||||
request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path;
|
||||
return Proxy.ProcessRequest(request);
|
||||
}
|
||||
|
||||
[WebInvoke(Method = "GET", UriTemplate = "{*path}"), OperationContract, AuthorizeTablesAccess, CLSCompliant(false)]
|
||||
public HttpResponseMessage HandleGet(HttpRequestMessage request, string path)
|
||||
{
|
||||
if (request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Resource.RequestCannotBeNullErrorMessage, Resource.RequestCannotBeNullErrorMessage);
|
||||
|
||||
request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path;
|
||||
return Proxy.ProcessRequest(request);
|
||||
}
|
||||
|
||||
[WebInvoke(Method = "DELETE", UriTemplate = "{*path}"), OperationContract, AuthorizeTablesAccess, CLSCompliant(false)]
|
||||
public HttpResponseMessage HandleDelete(HttpRequestMessage request, string path)
|
||||
{
|
||||
if (request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Resource.RequestCannotBeNullErrorMessage, Resource.RequestCannotBeNullErrorMessage);
|
||||
|
||||
request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path;
|
||||
return Proxy.ProcessRequest(request);
|
||||
}
|
||||
|
||||
[WebInvoke(Method = "MERGE", UriTemplate = "{*path}"), OperationContract, AuthorizeTablesAccess, CLSCompliant(false)]
|
||||
public HttpResponseMessage HandleMerge(HttpRequestMessage request, string path)
|
||||
{
|
||||
if (request == null)
|
||||
throw Extensions.StorageException(HttpStatusCode.BadRequest, Resource.RequestCannotBeNullErrorMessage, Resource.RequestCannotBeNullErrorMessage);
|
||||
|
||||
request.Properties[StorageProxyHandler.RequestedPathPropertyName] = path;
|
||||
return Proxy.ProcessRequest(request);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="aspnet.suppressformsredirect" version="0.0.1.4" />
|
||||
<package id="HttpClient" version="0.6.0" />
|
||||
<package id="JsonValue" version="0.6.0" />
|
||||
<package id="WebApi" version="0.6.0" />
|
||||
<package id="WebApi.All" version="0.6.0" />
|
||||
<package id="WebApi.Enhancements" version="0.6.0" />
|
||||
<package id="WebApi.OData" version="0.6.0" />
|
||||
<package id="AspNetWebApi" version="4.0.20126.16343" />
|
||||
<package id="AspNetWebApi.Core" version="4.0.20126.16343" />
|
||||
<package id="System.Json" version="4.0.20126.16343" />
|
||||
<package id="System.Net.Http" version="2.0.20126.16343" />
|
||||
<package id="System.Net.Http.Formatting" version="4.0.20126.16343" />
|
||||
<package id="System.Web.Http.Common" version="4.0.20126.16343" />
|
||||
</packages>
|
|
@ -12,6 +12,8 @@
|
|||
<AssemblyName>Common</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -81,6 +83,7 @@
|
|||
<Compile Include="Storage\ITableServiceEntity.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(SolutionDir)\.nuget\NuGet.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">
|
||||
|
|
|
@ -45,23 +45,23 @@ namespace Microsoft.WindowsAzure.Samples.Common.JobEngine.Conditions
|
|||
this.timer.Start();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
timer.Dispose();
|
||||
signal.Dispose();
|
||||
}
|
||||
|
||||
public Func<bool> TickFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
this.signal.WaitOne();
|
||||
return true;
|
||||
};
|
||||
{
|
||||
this.signal.WaitOne();
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.timer.Dispose();
|
||||
this.signal.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,5 +30,5 @@ namespace Microsoft.WindowsAzure.Samples.Common.JobEngine.Language
|
|||
{
|
||||
return new TaskBuilder<T>(condition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -72,12 +72,12 @@ namespace Microsoft.WindowsAzure.Samples.Common.JobEngine.Language
|
|||
public void Start(ExecutionModel execution)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(s =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Cycle();
|
||||
}
|
||||
});
|
||||
Cycle();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void Start()
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace Microsoft.WindowsAzure.Samples.Common.Storage
|
|||
|
||||
public AzureBlobContainer(CloudStorageAccount account, string containerName)
|
||||
: this(account, containerName.ToLowerInvariant(), false)
|
||||
{
|
||||
{
|
||||
}
|
||||
|
||||
public AzureBlobContainer(CloudStorageAccount account, string containerName, bool jsonpSupport)
|
||||
|
@ -74,7 +74,7 @@ namespace Microsoft.WindowsAzure.Samples.Common.Storage
|
|||
{
|
||||
permissions.PublicAccess = BlobContainerPublicAccessType.Container;
|
||||
}
|
||||
|
||||
|
||||
this.container.SetPermissions(permissions);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace Microsoft.WindowsAzure.Samples.Common.Storage
|
|||
entity.RowKey = Guid.NewGuid().ToString();
|
||||
Array.ForEach(
|
||||
entity.GetType().GetProperties(
|
||||
BindingFlags.Public | BindingFlags.Instance),
|
||||
BindingFlags.Public | BindingFlags.Instance),
|
||||
p =>
|
||||
{
|
||||
if ((p.Name != "PartitionKey") && (p.Name != "RowKey") && (p.Name != "Timestamp"))
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace Microsoft.WindowsAzure.Samples.Common.Storage
|
|||
blob.UploadText("text", "text");
|
||||
blob.ReleaseLease(leaseId);
|
||||
}
|
||||
|
||||
|
||||
public static string AcquireLease(this CloudBlob blob)
|
||||
{
|
||||
var creds = blob.ServiceClient.Credentials;
|
||||
|
|
Двоичный файл не отображается.
|
@ -27,6 +27,8 @@
|
|||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\Source\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -115,6 +117,7 @@
|
|||
</CodeAnalysisDictionary>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.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">
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution.
|
||||
|
||||
You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
|
||||
|
||||
1. You must give any other recipients of the Work or Derivative Works a copy of this License; and
|
||||
|
||||
2. You must cause any modified files to carry prominent notices stating that You changed the files; and
|
||||
|
||||
3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
|
||||
|
||||
4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions.
|
||||
|
||||
Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks.
|
||||
|
||||
This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability.
|
||||
|
||||
In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability.
|
||||
|
||||
While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
|
Двоичные данные
NuGet/NuGet.exe
Двоичные данные
NuGet/NuGet.exe
Двоичный файл не отображается.
|
@ -1 +0,0 @@
|
|||
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -22,6 +22,10 @@ namespace Microsoft.WindowsAzure.Samples.Phone.Notifications
|
|||
|
||||
public string ApplicationId { get; set; }
|
||||
|
||||
public string DeviceId { get; set; }
|
||||
public string ClientId { get; set; }
|
||||
|
||||
public string DeviceType { get; set; }
|
||||
|
||||
public string TileId { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,8 +20,8 @@ namespace Microsoft.WindowsAzure.Samples.Phone.Notifications
|
|||
|
||||
public interface IPushClient
|
||||
{
|
||||
void Connect(Action<PushRegistrationResponse> callback);
|
||||
void Register(Action<PushRegistrationResponse> callback, Uri tileNavigationUri = null);
|
||||
|
||||
void Disconnect(Action<PushRegistrationResponse> callback);
|
||||
void Unregister(Action<PushRegistrationResponse> callback, Uri tileNavigationUri = null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
namespace Microsoft.WindowsAzure.Samples.Phone.Notifications
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
|
@ -31,14 +32,13 @@ namespace Microsoft.WindowsAzure.Samples.Phone.Notifications
|
|||
private readonly Action<WebRequest> signRequestDelegate;
|
||||
private readonly Dispatcher dispatcher;
|
||||
private readonly string applicationId;
|
||||
private readonly string deviceId;
|
||||
private readonly string clientId;
|
||||
private readonly string deviceType;
|
||||
private readonly IList<Uri> notificationEndpoints = new List<Uri>();
|
||||
private static Uri primaryTileEnpointIdentifier = new Uri("/", UriKind.Relative);
|
||||
private string channelUri;
|
||||
|
||||
public PushClient(Uri endpointsServiceUri, Action<WebRequest> signRequestDelegate, string applicationId, string deviceId)
|
||||
: this(endpointsServiceUri, signRequestDelegate, applicationId, deviceId, null)
|
||||
{
|
||||
}
|
||||
|
||||
public PushClient(Uri endpointsServiceUri, Action<WebRequest> signRequestDelegate, string applicationId, string deviceId, Dispatcher dispatcher)
|
||||
public PushClient(Uri endpointsServiceUri, Action<WebRequest> signRequestDelegate, string applicationId, string clientId, string deviceType, Dispatcher dispatcher = null)
|
||||
{
|
||||
if (endpointsServiceUri == null)
|
||||
throw new ArgumentNullException("endpointsServiceUri");
|
||||
|
@ -49,48 +49,56 @@ namespace Microsoft.WindowsAzure.Samples.Phone.Notifications
|
|||
if (string.IsNullOrWhiteSpace(applicationId))
|
||||
throw new ArgumentNullException("applicationId");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(deviceId))
|
||||
throw new ArgumentNullException("deviceId");
|
||||
if (string.IsNullOrWhiteSpace(clientId))
|
||||
throw new ArgumentNullException("clientId");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(deviceType))
|
||||
throw new ArgumentNullException("deviceType");
|
||||
|
||||
this.endpointsServiceUri = endpointsServiceUri;
|
||||
this.signRequestDelegate = signRequestDelegate;
|
||||
this.applicationId = applicationId;
|
||||
this.deviceId = deviceId;
|
||||
this.clientId = clientId;
|
||||
this.deviceType = deviceType;
|
||||
this.dispatcher = dispatcher;
|
||||
}
|
||||
|
||||
public void Connect(Action<PushRegistrationResponse> callback)
|
||||
public void Register(Action<PushRegistrationResponse> callback, Uri tileNavigationUri = null)
|
||||
{
|
||||
EventHandler<PushContextErrorEventArgs> errorHandler = null;
|
||||
errorHandler =
|
||||
(s, e) =>
|
||||
{
|
||||
PushContext.Current.Error -= errorHandler;
|
||||
this.DispatchCallback(callback, new PushRegistrationResponse(false, e.Exception.Message));
|
||||
};
|
||||
|
||||
PushContext.Current.Error += errorHandler;
|
||||
PushContext.Current.Connect(
|
||||
c =>
|
||||
{
|
||||
PushContext.Current.Error -= errorHandler;
|
||||
|
||||
var endpoint = new Endpoint
|
||||
if (string.IsNullOrWhiteSpace(this.channelUri))
|
||||
{
|
||||
EventHandler<PushContextErrorEventArgs> errorHandler = null;
|
||||
errorHandler =
|
||||
(s, e) =>
|
||||
{
|
||||
ApplicationId = this.applicationId,
|
||||
DeviceId = this.deviceId,
|
||||
ChannelUri = c.ChannelUri.ToString()
|
||||
PushContext.Current.Error -= errorHandler;
|
||||
this.DispatchCallback(callback, new PushRegistrationResponse(false, e.Exception.Message));
|
||||
};
|
||||
|
||||
this.PutEndpoint(endpoint, callback);
|
||||
});
|
||||
PushContext.Current.Error += errorHandler;
|
||||
PushContext.Current.Connect(
|
||||
c =>
|
||||
{
|
||||
PushContext.Current.Error -= errorHandler;
|
||||
|
||||
this.channelUri = c.ChannelUri.AbsoluteUri;
|
||||
this.PutEndpoint(tileNavigationUri, callback);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
this.PutEndpoint(tileNavigationUri, callback);
|
||||
}
|
||||
}
|
||||
|
||||
public void Disconnect(Action<PushRegistrationResponse> callback)
|
||||
public void Unregister(Action<PushRegistrationResponse> callback, Uri tileNavigationUri = null)
|
||||
{
|
||||
this.DeleteEndpoint(callback);
|
||||
this.DeleteEndpoint(callback, tileNavigationUri);
|
||||
|
||||
PushContext.Current.Disconnect();
|
||||
if (this.notificationEndpoints.Count == 0)
|
||||
{
|
||||
PushContext.Current.Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void DispatchCallback(Action<PushRegistrationResponse> callback, PushRegistrationResponse response)
|
||||
|
@ -109,8 +117,23 @@ namespace Microsoft.WindowsAzure.Samples.Phone.Notifications
|
|||
return (HttpWebRequest)WebRequestCreator.ClientHttp.Create(requestUri);
|
||||
}
|
||||
|
||||
private void PutEndpoint(Endpoint endpoint, Action<PushRegistrationResponse> callback)
|
||||
private void PutEndpoint(Uri tileNavigationUri, Action<PushRegistrationResponse> callback)
|
||||
{
|
||||
var endpointIdentifier = tileNavigationUri ?? primaryTileEnpointIdentifier;
|
||||
|
||||
if (this.notificationEndpoints.Contains(endpointIdentifier)) throw new InvalidOperationException("Navigation Uri already registered.");
|
||||
|
||||
var endpoint = new Endpoint
|
||||
{
|
||||
ApplicationId = this.applicationId,
|
||||
ClientId = this.clientId,
|
||||
DeviceType = this.deviceType,
|
||||
ChannelUri = this.channelUri,
|
||||
TileId = tileNavigationUri != null ?
|
||||
tileNavigationUri.ToString() :
|
||||
string.Empty
|
||||
};
|
||||
|
||||
var request = this.ResolveRequest(this.endpointsServiceUri);
|
||||
request.Method = "PUT";
|
||||
request.ContentType = "application/json";
|
||||
|
@ -145,10 +168,11 @@ namespace Microsoft.WindowsAzure.Samples.Phone.Notifications
|
|||
if ((response != null) && (response.StatusCode == HttpStatusCode.Accepted))
|
||||
{
|
||||
this.DispatchCallback(callback, new PushRegistrationResponse(true, string.Empty));
|
||||
this.notificationEndpoints.Add(endpointIdentifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.DispatchCallback(callback, new PushRegistrationResponse(false, "The push notification channel coud not be registered in the Endpoints service."));
|
||||
this.DispatchCallback(callback, new PushRegistrationResponse(false, "The specified endpoint could not be registered in the Endpoints service."));
|
||||
}
|
||||
}
|
||||
catch (WebException webException)
|
||||
|
@ -170,10 +194,26 @@ namespace Microsoft.WindowsAzure.Samples.Phone.Notifications
|
|||
}
|
||||
}
|
||||
|
||||
private void DeleteEndpoint(Action<PushRegistrationResponse> callback)
|
||||
private void DeleteEndpoint(Action<PushRegistrationResponse> callback, Uri tileNavigationUri)
|
||||
{
|
||||
var endpointIdentifier = tileNavigationUri ?? primaryTileEnpointIdentifier;
|
||||
|
||||
if (!this.notificationEndpoints.Contains(endpointIdentifier)) throw new InvalidOperationException("Navigation Uri is not registered. Call register method first.");
|
||||
|
||||
var builder = new UriBuilder(this.endpointsServiceUri);
|
||||
builder.Path += string.Format(CultureInfo.InvariantCulture, "/{0}/{1}", this.applicationId, this.deviceId);
|
||||
builder.Path += string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"/{0}/{1}",
|
||||
this.applicationId,
|
||||
this.clientId);
|
||||
|
||||
if (tileNavigationUri != null)
|
||||
{
|
||||
builder.Query = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"tileId={0}",
|
||||
tileNavigationUri.ToString());
|
||||
}
|
||||
|
||||
var request = this.ResolveRequest(builder.Uri);
|
||||
request.Method = "DELETE";
|
||||
|
@ -190,10 +230,11 @@ namespace Microsoft.WindowsAzure.Samples.Phone.Notifications
|
|||
if ((response != null) && (response.StatusCode == HttpStatusCode.Accepted))
|
||||
{
|
||||
this.DispatchCallback(callback, new PushRegistrationResponse(true, string.Empty));
|
||||
this.notificationEndpoints.Remove(endpointIdentifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.DispatchCallback(callback, new PushRegistrationResponse(false, "The push notification channel coud not be unregistered in the Endpoints service."));
|
||||
this.DispatchCallback(callback, new PushRegistrationResponse(false, "The specified endpoint could not be unregistered in the Endpoints service."));
|
||||
}
|
||||
}
|
||||
catch (WebException webException)
|
||||
|
@ -203,6 +244,10 @@ namespace Microsoft.WindowsAzure.Samples.Phone.Notifications
|
|||
},
|
||||
null);
|
||||
}
|
||||
catch (InvalidOperationException exception)
|
||||
{
|
||||
this.DispatchCallback(callback, new PushRegistrationResponse(false, exception.Message));
|
||||
}
|
||||
catch (ArgumentNullException exception)
|
||||
{
|
||||
this.DispatchCallback(callback, new PushRegistrationResponse(false, exception.Message));
|
||||
|
|
|
@ -42,6 +42,8 @@ namespace Microsoft.WindowsAzure.Samples.Phone.Notifications
|
|||
|
||||
public string ApplicationId { get; set; }
|
||||
|
||||
public string DeviceId { get; set; }
|
||||
public string ClientId { get; set; }
|
||||
|
||||
public string DeviceType { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -109,7 +109,7 @@ namespace Microsoft.WindowsAzure.Samples.Phone.Notifications
|
|||
|
||||
public IPushClient ResolvePushClient()
|
||||
{
|
||||
return new PushClient(this.Configuration.EndpointsServiceUri, this.Configuration.SignRequest, this.Configuration.ApplicationId, this.Configuration.DeviceId, this.Configuration.Dispatcher);
|
||||
return new PushClient(this.Configuration.EndpointsServiceUri, this.Configuration.SignRequest, this.Configuration.ApplicationId, this.Configuration.ClientId, this.Configuration.DeviceType, this.Configuration.Dispatcher);
|
||||
}
|
||||
|
||||
public void Connect(Action<HttpNotificationChannel> callback)
|
||||
|
@ -126,6 +126,7 @@ namespace Microsoft.WindowsAzure.Samples.Phone.Notifications
|
|||
{
|
||||
// First, try to pick up an existing channel.
|
||||
this.NotificationChannel = HttpNotificationChannel.Find(this.config.ChannelName);
|
||||
|
||||
if (this.NotificationChannel == null)
|
||||
{
|
||||
this.CreateChannel(callback);
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<TargetFrameworkProfile />
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -124,6 +126,7 @@
|
|||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(SolutionDir)\.nuget\NuGet.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">
|
||||
|
|
Загрузка…
Ссылка в новой задаче