REST client API: Dev (SPRNET-1345)
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Core.2008", "..\..\..\src\Spring\Spring.Core\Spring.Core.2008.csproj", "{710961A3-0DF4-49E4-A26E-F5B9C044AC84}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Http.2008", "..\..\..\src\Spring\Spring.Http\Spring.Http.2008.csproj", "{FAC04F79-4B1F-1D13-B30F-00EE04EC0FBC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Http.Tests.2008", "..\..\..\test\Spring\Spring.Http.Tests\Spring.Http.Tests.2008.csproj", "{F04CEE18-3897-A399-46BF-459437475B21}"
|
||||
@@ -14,10 +12,6 @@ Global
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{710961A3-0DF4-49E4-A26E-F5B9C044AC84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{710961A3-0DF4-49E4-A26E-F5B9C044AC84}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{710961A3-0DF4-49E4-A26E-F5B9C044AC84}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{710961A3-0DF4-49E4-A26E-F5B9C044AC84}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FAC04F79-4B1F-1D13-B30F-00EE04EC0FBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FAC04F79-4B1F-1D13-B30F-00EE04EC0FBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FAC04F79-4B1F-1D13-B30F-00EE04EC0FBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual Studio 2010
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Core.2010", "..\..\..\src\Spring\Spring.Core\Spring.Core.2010.csproj", "{710961A3-0DF4-49E4-A26E-F5B9C044AC84}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Http.2010", "..\..\..\src\Spring\Spring.Http\Spring.Http.2010.csproj", "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Http.Tests.2010", "..\..\..\test\Spring\Spring.Http.Tests\Spring.Http.Tests.2010.csproj", "{4594CEE7-3897-A3BF-9946-5B4374F01821}"
|
||||
@@ -14,10 +12,6 @@ Global
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{710961A3-0DF4-49E4-A26E-F5B9C044AC84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{710961A3-0DF4-49E4-A26E-F5B9C044AC84}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{710961A3-0DF4-49E4-A26E-F5B9C044AC84}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{710961A3-0DF4-49E4-A26E-F5B9C044AC84}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
using Spring.Http.Rest;
|
||||
|
||||
@@ -11,9 +13,19 @@ namespace Spring.RestQuickStart
|
||||
try
|
||||
{
|
||||
RestTemplate rt = new RestTemplate("http://twitter.com");
|
||||
string result = rt.GetForObject<string>("/statuses/user_timeline.xml?id={id}", "lancearmstrong");
|
||||
|
||||
Console.WriteLine(result);
|
||||
//string result = rt.GetForObject<string>("/statuses/user_timeline.xml?id={id}&count={2}", "SpringForNet", "10");
|
||||
//Console.WriteLine(result);
|
||||
|
||||
XElement result = rt.GetForObject<XElement>("/statuses/user_timeline.xml?id={id}&count={2}", "SpringForNet", "10");
|
||||
var tweets = from el in result.Elements("status")
|
||||
select el.Element("text").Value;
|
||||
foreach (string tweet in tweets)
|
||||
{
|
||||
Console.WriteLine(String.Format("* {0}", tweet));
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -32,6 +32,10 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.XML" />
|
||||
<Reference Include="System.Xml.Linq">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
@@ -40,10 +44,6 @@
|
||||
<Compile Include="Program.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Spring\Spring.Core\Spring.Core.2008.csproj">
|
||||
<Project>{710961A3-0DF4-49E4-A26E-F5B9C044AC84}</Project>
|
||||
<Name>Spring.Core.2008</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Spring\Spring.Http\Spring.Http.2008.csproj">
|
||||
<Project>{FAC04F79-4B1F-1D13-B30F-00EE04EC0FBC}</Project>
|
||||
<Name>Spring.Http.2008</Name>
|
||||
|
||||
@@ -52,6 +52,8 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.XML" />
|
||||
<Reference Include="System.Xml.Linq">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
@@ -60,10 +62,6 @@
|
||||
<Compile Include="Program.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Spring\Spring.Core\Spring.Core.2010.csproj">
|
||||
<Project>{710961A3-0DF4-49E4-A26E-F5B9C044AC84}</Project>
|
||||
<Name>Spring.Core.2010</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Spring\Spring.Http\Spring.Http.2010.csproj">
|
||||
<Project>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</Project>
|
||||
<Name>Spring.Http.2010</Name>
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -26,17 +27,17 @@ using Spring.Util;
|
||||
|
||||
namespace Spring.Http.Converters
|
||||
{
|
||||
/**
|
||||
* Abstract base class for most {@link HttpMessageConverter} implementations.
|
||||
*
|
||||
* <p>This base class adds support for setting supported {@code MediaTypes}, through the
|
||||
* {@link #setSupportedMediaTypes(List) supportedMediaTypes} bean property. It also adds
|
||||
* support for {@code Content-Type} and {@code Content-Length} when writing to output messages.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
/// <summary>
|
||||
/// Base class for most <see cref="IHttpMessageConverter"/> implementations.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This base class adds support for setting supported <see cref="MediaType"/>s, through the
|
||||
/// <see cref="P:SupportedMediaTypes"/> property.
|
||||
/// It also adds support for 'Content-Type' when writing to the HTTP request.
|
||||
/// </remarks>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
public abstract class AbstractHttpMessageConverter : IHttpMessageConverter
|
||||
{
|
||||
#region Logging
|
||||
@@ -47,9 +48,9 @@ namespace Spring.Http.Converters
|
||||
|
||||
private IList<MediaType> _supportedMediaTypes = new List<MediaType>();
|
||||
|
||||
/**
|
||||
* Set the list of {@link MediaType} objects supported by this converter.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Gets or sets the list of <see cref="MediaType"/> objects supported by this converter.
|
||||
/// </summary>
|
||||
public IList<MediaType> SupportedMediaTypes
|
||||
{
|
||||
get { return _supportedMediaTypes; }
|
||||
@@ -58,18 +59,19 @@ namespace Spring.Http.Converters
|
||||
|
||||
#region Constructor(s)
|
||||
|
||||
/**
|
||||
* Construct an {@code AbstractHttpMessageConverter} with no supported media types.
|
||||
* @see #setSupportedMediaTypes
|
||||
*/
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="AbstractHttpMessageConverter"/>
|
||||
/// with no supported media types.
|
||||
/// </summary>
|
||||
protected AbstractHttpMessageConverter()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an {@code AbstractHttpMessageConverter} with multiple supported media type.
|
||||
* @param supportedMediaTypes the supported media types
|
||||
*/
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="AbstractHttpMessageConverter"/>
|
||||
/// with multiple supported media type.
|
||||
/// </summary>
|
||||
/// <param name="supportedMediaTypes">The supported media types.</param>
|
||||
protected AbstractHttpMessageConverter(params MediaType[] supportedMediaTypes)
|
||||
{
|
||||
this._supportedMediaTypes = new List<MediaType>(supportedMediaTypes);
|
||||
@@ -79,47 +81,80 @@ namespace Spring.Http.Converters
|
||||
|
||||
#region IHttpMessageConverter Membres
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>This implementation checks if the given class is {@linkplain #supports(Class) supported},
|
||||
* and if the {@linkplain #getSupportedMediaTypes() supported media types}
|
||||
* {@linkplain MediaType#includes(MediaType) include} the given media type.
|
||||
*/
|
||||
public bool CanRead(Type type, MediaType mediaType)
|
||||
/// <summary>
|
||||
/// Indicates whether the given class can be read by this converter.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This implementation checks if the given class is <see cref="M:Supports(Type)">supported</see>,
|
||||
/// and if the <see cref="P:SupportedMediaTypes">supported media types</see> <see cref="M:MediaType.Includes(MediaType)">include</see>
|
||||
/// the given media type.
|
||||
/// </remarks>
|
||||
/// <param name="type">The class to test for readability</param>
|
||||
/// <param name="mediaType">
|
||||
/// The media type to read, can be null if not specified. Typically the value of a 'Content-Type' header.
|
||||
/// </param>
|
||||
/// <returns><see langword="true"/> if readable; otherwise <see langword="false"/></returns>
|
||||
public bool CanRead(Type type, MediaType mediaType)
|
||||
{
|
||||
return Supports(type) && CanRead(mediaType);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>This implementation checks if the given class is {@linkplain #supports(Class) supported},
|
||||
* and if the {@linkplain #getSupportedMediaTypes() supported media types}
|
||||
* {@linkplain MediaType#includes(MediaType) include} the given media type.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Indicates whether the given class can be written by this converter.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This implementation checks if the given class is <see cref="M:Supports(Type)">supported</see>,
|
||||
/// and if the <see cref="P:SupportedMediaTypes">supported media types</see> <see cref="M:MediaType.Includes(MediaType)">include</see>
|
||||
/// the given media type.
|
||||
/// </remarks>
|
||||
/// <param name="type">The class to test for writability</param>
|
||||
/// <param name="mediaType">
|
||||
/// The media type to write, can be null if not specified. Typically the value of an 'Accept' header.
|
||||
/// </param>
|
||||
/// <returns><see langword="true"/> if writable; otherwise <see langword="false"/></returns>
|
||||
public bool CanWrite(Type type, MediaType mediaType)
|
||||
{
|
||||
return Supports(type) && CanWrite(mediaType);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>This implementation simple delegates to {@link #readInternal(Class, HttpInputMessage)}.
|
||||
* Future implementations might add some default behavior, however.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Read an object of the given type form the given HTTP response, and returns it.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This implementation simple delegates to <see cre="ReadInternal"/> method.
|
||||
/// Future implementations might add some default behavior, however.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">
|
||||
/// The type of object to return. This type must have previously been passed to the
|
||||
/// <see cref="M:CanRead"/> method of this interface, which must have returned <see langword="true"/>.
|
||||
/// </typeparam>
|
||||
/// <param name="response">The HTTP response to read from.</param>
|
||||
/// <returns>The converted object.</returns>
|
||||
public T Read<T>(HttpWebResponse response) where T : class
|
||||
{
|
||||
return ReadInternal<T>(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>This implementation delegates to {@link #getDefaultContentType(Object)} if a content
|
||||
* type was not provided, calls {@link #getContentLength}, and sets the corresponding headers
|
||||
* on the output message. It then calls {@link #writeInternal}.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Write an given object to the given HTTP request.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This implementation delegates to <see cref="M:GetDefaultContentType"/> method if a content
|
||||
/// type was not provided, and calls <see cref="M:WriteInternal"/>.
|
||||
/// </remarks>
|
||||
/// <param name="content">
|
||||
/// The object to write to the HTTP request. The type of this object must have previously been
|
||||
/// passed to the <see cref="M:CanWrite"/> method of this interface, which must have returned <see langword="true"/>.
|
||||
/// </param>
|
||||
/// <param name="mediaType">
|
||||
/// The content type to use when writing. May be null to indicate that the default content type of the converter must be used.
|
||||
/// If not null, this media type must have previously been passed to the <see cref="M:CanWrite"/> method of this interface,
|
||||
/// which must have returned <see langword="true"/>.
|
||||
/// </param>
|
||||
/// <param name="request">The HTTP request to write to.</param>
|
||||
public void Write(object content, MediaType mediaType, HttpWebRequest request)
|
||||
{
|
||||
if (!StringUtils.HasText(request.Headers[HttpRequestHeader.ContentType]))
|
||||
if (!StringUtils.HasText(request.ContentType))
|
||||
{
|
||||
if (mediaType == null || mediaType.IsWildcardType || mediaType.IsWildcardSubtype)
|
||||
{
|
||||
@@ -135,14 +170,16 @@ namespace Spring.Http.Converters
|
||||
|
||||
#endregion
|
||||
|
||||
/**
|
||||
* Returns true if any of the {@linkplain #setSupportedMediaTypes(List) supported media types}
|
||||
* include the given media type.
|
||||
* @param mediaType the media type to read, can be {@code null} if not specified. Typically the value of a
|
||||
* {@code Content-Type} header.
|
||||
* @return true if the supported media types include the media type, or if the media type is {@code null}
|
||||
*/
|
||||
protected bool CanRead(MediaType mediaType)
|
||||
/// <summary>
|
||||
/// Returns true if any of the <see cref="P:SupportedMediaTypes">supported media types</see> include the given media type.
|
||||
/// </summary>
|
||||
/// <param name="mediaType">
|
||||
/// The media type to read, can be null if not specified. Typically the value of a 'Content-Type' header.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the supported media types include the media type, or if the media type is null.
|
||||
/// </returns>
|
||||
protected bool CanRead(MediaType mediaType)
|
||||
{
|
||||
if (mediaType == null)
|
||||
{
|
||||
@@ -158,13 +195,15 @@ namespace Spring.Http.Converters
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given media type includes any of the
|
||||
* {@linkplain #setSupportedMediaTypes(List) supported media types}.
|
||||
* @param mediaType the media type to write, can be {@code null} if not specified. Typically the value of an
|
||||
* {@code Accept} header.
|
||||
* @return true if the supported media types are compatible with the media type, or if the media type is {@code null}
|
||||
*/
|
||||
/// <summary>
|
||||
/// Returns true if the given media type includes any of the <see cref="P:SupportedMediaTypes">supported media types</see>.
|
||||
/// </summary>
|
||||
/// <param name="mediaType">
|
||||
/// The media type to write, can be {@code null} if not specified. Typically the value of an 'Accept' header.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the supported media types are compatible with the media type, or if the media type is null.
|
||||
/// </returns>
|
||||
protected bool CanWrite(MediaType mediaType)
|
||||
{
|
||||
if (mediaType == null || mediaType.Equals(MediaType.ALL))
|
||||
@@ -181,44 +220,74 @@ namespace Spring.Http.Converters
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default content type for the given type. Called when {@link #write}
|
||||
* is invoked without a specified content type parameter.
|
||||
* <p>By default, this returns the first element of the
|
||||
* {@link #setSupportedMediaTypes(List) supportedMediaTypes} property, if any.
|
||||
* Can be overridden in subclasses.
|
||||
* @param t the type to return the content type for
|
||||
* @return the content type, or <code>null</code> if not known
|
||||
*/
|
||||
/// <summary>
|
||||
/// Returns the default content type for the given type.
|
||||
/// Called when <see cref="M:Write"/> is invoked without a specified content type parameter.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default, this returns the first element of the <see cref="P:SupportedMediaTypes"/> property, if any.
|
||||
/// </remarks>
|
||||
/// <param name="type">The type to return the content type for.</param>
|
||||
/// <returns>The <see cref="MediaType">content type</see>, or null if not known.</returns>
|
||||
protected virtual MediaType GetDefaultContentType(Type type)
|
||||
{
|
||||
return (this._supportedMediaTypes.Count > 0 ? this._supportedMediaTypes[0] : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the given class is supported by this converter.
|
||||
* @param clazz the class to test for support
|
||||
* @return <code>true</code> if supported; <code>false</code> otherwise
|
||||
*/
|
||||
/// <summary>
|
||||
/// Indicates whether the given class is supported by this converter.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to test for support.</param>
|
||||
/// <returns><see langword="true"/> if supported; otherwise <see langword="false"/></returns>
|
||||
protected abstract bool Supports(Type type);
|
||||
|
||||
/**
|
||||
* Abstract template method that reads the actualy object. Invoked from {@link #read}.
|
||||
* @param clazz the type of object to return
|
||||
* @param inputMessage the HTTP input message to read from
|
||||
* @return the converted object
|
||||
* @throws IOException in case of I/O errors
|
||||
* @throws HttpMessageNotReadableException in case of conversion errors
|
||||
*/
|
||||
/// <summary>
|
||||
/// Abstract template method that reads the actualy object. Invoked from <see cref="M:Read"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object to return.</typeparam>
|
||||
/// <param name="response">The HTTP response to read from.</param>
|
||||
/// <returns>The converted object.</returns>
|
||||
protected abstract T ReadInternal<T>(HttpWebResponse response) where T : class;
|
||||
|
||||
/**
|
||||
* Abstract template method that writes the actual body. Invoked from {@link #write}.
|
||||
* @param t the object to write to the output message
|
||||
* @param outputMessage the message to write to
|
||||
* @throws IOException in case of I/O errors
|
||||
* @throws HttpMessageNotWritableException in case of conversion errors
|
||||
*/
|
||||
/// <summary>
|
||||
/// Abstract template method that writes the actual body. Invoked from <see cref="M:Write"/>.
|
||||
/// </summary>
|
||||
/// <param name="content">The object to write to the HTTP request.</param>
|
||||
/// <param name="request">The HTTP request to write to.</param>
|
||||
protected abstract void WriteInternal(object content, HttpWebRequest request);
|
||||
|
||||
#region Inner class definitions
|
||||
|
||||
// TODO : Move this class
|
||||
internal class IgnoreCloseMemoryStream : MemoryStream
|
||||
{
|
||||
public IgnoreCloseMemoryStream()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
}
|
||||
|
||||
public void CopyToAndClose(Stream dest)
|
||||
{
|
||||
this.Position = 0;
|
||||
|
||||
int bufferSize = 65536;
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
|
||||
int bytesCount;
|
||||
while ((bytesCount = this.Read(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
dest.Write(buffer, 0, bytesCount);
|
||||
}
|
||||
dest.Flush();
|
||||
|
||||
base.Close();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,29 +25,43 @@ using System.Text;
|
||||
|
||||
namespace Spring.Http.Converters
|
||||
{
|
||||
/**
|
||||
* Implementation of {@link HttpMessageConverter} that can read and write byte arrays.
|
||||
*
|
||||
* <p>By default, this converter supports all media types (<code>*/*</code>), and writes with a {@code
|
||||
* Content-Type} of {@code application/octet-stream}. This can be overridden by setting the {@link
|
||||
* #setSupportedMediaTypes(java.util.List) supportedMediaTypes} property.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="IHttpMessageConverter"/> that can read and write byte arrays.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default, this converter supports all media types '*/*', and writes with a 'Content-Type'
|
||||
/// of 'application/octet-stream'.
|
||||
/// This can be overridden by setting the <see cref="P:SupportedMediaTypes"/> property.
|
||||
/// </remarks>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
public class ByteArrayHttpMessageConverter : AbstractHttpMessageConverter
|
||||
{
|
||||
/** Creates a new instance of the {@code ByteArrayHttpMessageConverter}. */
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="ByteArrayHttpMessageConverter"/>
|
||||
/// with 'application/octet-stream', and '*/*' media types.
|
||||
/// </summary>
|
||||
public ByteArrayHttpMessageConverter() :
|
||||
base(new MediaType("application", "octet-stream"), MediaType.ALL)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the given class is supported by this converter.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to test for support.</param>
|
||||
/// <returns><see langword="true"/> if supported; otherwise <see langword="false"/></returns>
|
||||
protected override bool Supports(Type type)
|
||||
{
|
||||
return type.Equals(typeof(byte[]));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract template method that reads the actualy object. Invoked from <see cref="M:Read"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object to return.</typeparam>
|
||||
/// <param name="response">The HTTP response to read from.</param>
|
||||
/// <returns>The converted object.</returns>
|
||||
protected override T ReadInternal<T>(HttpWebResponse response)
|
||||
{
|
||||
// Get the response stream
|
||||
@@ -57,6 +71,11 @@ namespace Spring.Http.Converters
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract template method that writes the actual body. Invoked from <see cref="M:Write"/>.
|
||||
/// </summary>
|
||||
/// <param name="content">The object to write to the HTTP request.</param>
|
||||
/// <param name="request">The HTTP request to write to.</param>
|
||||
protected override void WriteInternal(object content, HttpWebRequest request)
|
||||
{
|
||||
// Create a byte array of the data we want to send
|
||||
@@ -65,7 +84,7 @@ namespace Spring.Http.Converters
|
||||
// Set the content length in the request headers
|
||||
request.ContentLength = byteData.Length;
|
||||
|
||||
// Write data
|
||||
// Write to the request
|
||||
using (Stream postStream = request.GetRequestStream())
|
||||
{
|
||||
postStream.Write(byteData, 0, byteData.Length);
|
||||
|
||||
@@ -28,27 +28,58 @@ using Spring.Http.Converters.Xml;
|
||||
|
||||
namespace Spring.Http.Converters.Feed
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for Atom and RSS Feed message converters
|
||||
/// using the <see cref="System.ServiceModel.Syndication.SyndicationFeed"/> class.
|
||||
/// </summary>
|
||||
/// <author>Bruno Baia</author>
|
||||
public abstract class AbstractFeedHttpMessageConverter : AbstractXmlHttpMessageConverter
|
||||
{
|
||||
/**
|
||||
* Construct an {@code AbstractHttpMessageConverter} with multiple supported media type.
|
||||
* @param supportedMediaTypes the supported media types
|
||||
*/
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="AbstractXmlHttpMessageConverter"/>
|
||||
/// with multiple supported media type.
|
||||
/// </summary>
|
||||
/// <param name="supportedMediaTypes">The supported media types.</param>
|
||||
protected AbstractFeedHttpMessageConverter(params MediaType[] supportedMediaTypes) :
|
||||
base(supportedMediaTypes)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the given class is supported by this converter.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to test for support.</param>
|
||||
/// <returns><see langword="true"/> if supported; otherwise <see langword="false"/></returns>
|
||||
protected override bool Supports(Type type)
|
||||
{
|
||||
return type.Equals(typeof(SyndicationFeed));
|
||||
return type.Equals(typeof(SyndicationFeed)) || type.Equals(typeof(SyndicationItem));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract template method that reads the actualy object using a <see cref="XmlReader"/>. Invoked from <see cref="M:ReadInternal"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object to return.</typeparam>
|
||||
/// <param name="xmlReader">The XmlReader to use.</param>
|
||||
/// <param name="response">The HTTP response to read from.</param>
|
||||
/// <returns>The converted object.</returns>
|
||||
protected override T ReadXml<T>(XmlReader xmlReader, HttpWebResponse response)
|
||||
{
|
||||
return SyndicationFeed.Load(xmlReader) as T;
|
||||
if (typeof(SyndicationFeed).Equals(typeof(T)))
|
||||
{
|
||||
return SyndicationFeed.Load(xmlReader) as T;
|
||||
}
|
||||
if (typeof(SyndicationItem).Equals(typeof(T)))
|
||||
{
|
||||
return SyndicationItem.Load(xmlReader) as T;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the default <see cref="XmlReaderSettings">XmlReader settings</see>
|
||||
/// used by this converter to read from the HTTP response.
|
||||
/// </summary>
|
||||
/// <returns>The XmlReader settings.</returns>
|
||||
protected override XmlReaderSettings GetDefaultXmlReaderSettings()
|
||||
{
|
||||
XmlReaderSettings settings = new XmlReaderSettings();
|
||||
|
||||
@@ -26,17 +26,44 @@ using System.ServiceModel.Syndication;
|
||||
|
||||
namespace Spring.Http.Converters.Feed
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="IHttpMessageConverter"/> that can read and write Atom feeds
|
||||
/// using the <see cref="System.ServiceModel.Syndication.SyndicationFeed"/> class.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default, this converter reads and writes the media type 'application/atom+xml' media type.
|
||||
/// This can be overridden by setting the <see cref="P:SupportedMediaTypes"/> property.
|
||||
/// </remarks>
|
||||
/// <author>Bruno Baia</author>
|
||||
public class Atom10FeedHttpMessageConverter : AbstractFeedHttpMessageConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="Atom10FeedHttpMessageConverter"/>
|
||||
/// with 'application/atom+xml', 'application/xml' and 'text/xml' media types.
|
||||
/// </summary>
|
||||
public Atom10FeedHttpMessageConverter() :
|
||||
base(new MediaType("application", "atom+xml"))
|
||||
base(new MediaType("application", "atom+xml"), new MediaType("application", "xml"), new MediaType("text", "xml"))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract template method that writes the actual body using a <see cref="XmlWriter"/>. Invoked from <see cref="M:WriteInternal"/>.
|
||||
/// </summary>
|
||||
/// <param name="xmlWriter">The XmlWriter to use.</param>
|
||||
/// <param name="content">The object to write to the HTTP request.</param>
|
||||
/// <param name="request">The HTTP request to write to.</param>
|
||||
protected override void WriteXml(XmlWriter xmlWriter, object content, HttpWebRequest request)
|
||||
{
|
||||
SyndicationFeed rssFeed = content as SyndicationFeed;
|
||||
rssFeed.SaveAsAtom10(xmlWriter);
|
||||
if (content is SyndicationFeed)
|
||||
{
|
||||
SyndicationFeed atomFeed = content as SyndicationFeed;
|
||||
atomFeed.SaveAsAtom10(xmlWriter);
|
||||
}
|
||||
else if (content is SyndicationItem)
|
||||
{
|
||||
SyndicationItem atomItem = content as SyndicationItem;
|
||||
atomItem.SaveAsAtom10(xmlWriter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#if NET_3_5
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Xml;
|
||||
using System.ServiceModel.Syndication;
|
||||
|
||||
namespace Spring.Http.Converters.Feed
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="IHttpMessageConverter"/> that can read and write RSS feeds
|
||||
/// using the <see cref="System.ServiceModel.Syndication.SyndicationFeed"/> class.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default, this converter reads and writes the media type 'application/rss+xml' media type.
|
||||
/// This can be overridden by setting the <see cref="P:SupportedMediaTypes"/> property.
|
||||
/// </remarks>
|
||||
/// <author>Bruno Baia</author>
|
||||
public class Rss20FeedHttpMessageConverter : AbstractFeedHttpMessageConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="Rss20FeedHttpMessageConverter"/>
|
||||
/// with 'application/rss+xml', 'application/xml' and 'text/xml' media types.
|
||||
/// </summary>
|
||||
public Rss20FeedHttpMessageConverter() :
|
||||
base(new MediaType("application", "rss+xml"), new MediaType("application", "xml"), new MediaType("text", "xml"))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract template method that writes the actual body using a <see cref="XmlWriter"/>. Invoked from <see cref="M:WriteInternal"/>.
|
||||
/// </summary>
|
||||
/// <param name="xmlWriter">The XmlWriter to use.</param>
|
||||
/// <param name="content">The object to write to the HTTP request.</param>
|
||||
/// <param name="request">The HTTP request to write to.</param>
|
||||
protected override void WriteXml(XmlWriter xmlWriter, object content, HttpWebRequest request)
|
||||
{
|
||||
if (content is SyndicationFeed)
|
||||
{
|
||||
SyndicationFeed rssFeed = content as SyndicationFeed;
|
||||
rssFeed.SaveAsRss20(xmlWriter);
|
||||
}
|
||||
else if (content is SyndicationItem)
|
||||
{
|
||||
SyndicationItem rssItem = content as SyndicationItem;
|
||||
rssItem.SaveAsRss20(xmlWriter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,43 +0,0 @@
|
||||
#if NET_3_5
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Xml;
|
||||
using System.ServiceModel.Syndication;
|
||||
|
||||
namespace Spring.Http.Converters.Feed
|
||||
{
|
||||
public class Rss20FeedHttpMessageConverter : AbstractFeedHttpMessageConverter
|
||||
{
|
||||
public Rss20FeedHttpMessageConverter() :
|
||||
base(new MediaType("application", "rss+xml"))
|
||||
{
|
||||
}
|
||||
|
||||
protected override void WriteXml(XmlWriter xmlWriter, object content, HttpWebRequest request)
|
||||
{
|
||||
SyndicationFeed rssFeed = content as SyndicationFeed;
|
||||
rssFeed.SaveAsRss20(xmlWriter);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -24,62 +24,65 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Spring.Http.Converters
|
||||
{
|
||||
/**
|
||||
* Strategy interface that specifies a converter that can convert from and to HTTP requests and responses.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
// TODO: HttpMessageNotReadableException & HttpMessageNotWritableException exceptions ?
|
||||
|
||||
/// <summary>
|
||||
/// Strategy interface that specifies a converter that can convert from and to HTTP requests and responses.
|
||||
/// </summary>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
public interface IHttpMessageConverter
|
||||
{
|
||||
/**
|
||||
* Indicates whether the given class can be read by this converter.
|
||||
* @param clazz the class to test for readability
|
||||
* @param mediaType the media type to read, can be {@code null} if not specified. Typically the value of a
|
||||
* {@code Content-Type} header.
|
||||
* @return {@code true} if readable; {@code false} otherwise
|
||||
*/
|
||||
/// <summary>
|
||||
/// Indicates whether the given class can be read by this converter.
|
||||
/// </summary>
|
||||
/// <param name="type">The class to test for readability</param>
|
||||
/// <param name="mediaType">
|
||||
/// The media type to read, can be null if not specified. Typically the value of a 'Content-Type' header.
|
||||
/// </param>
|
||||
/// <returns><see langword="true"/> if readable; otherwise <see langword="false"/></returns>
|
||||
bool CanRead(Type type, MediaType mediaType);
|
||||
|
||||
/**
|
||||
* Indicates whether the given class can be written by this converter.
|
||||
* @param clazz the class to test for writability
|
||||
* @param mediaType the media type to write, can be {@code null} if not specified. Typically the value of an
|
||||
* {@code Accept} header.
|
||||
* @return {@code true} if writable; {@code false} otherwise
|
||||
*/
|
||||
/// <summary>
|
||||
/// Indicates whether the given class can be written by this converter.
|
||||
/// </summary>
|
||||
/// <param name="type">The class to test for writability</param>
|
||||
/// <param name="mediaType">
|
||||
/// The media type to write, can be null if not specified. Typically the value of an 'Accept' header.
|
||||
/// </param>
|
||||
/// <returns><see langword="true"/> if writable; otherwise <see langword="false"/></returns>
|
||||
bool CanWrite(Type type, MediaType mediaType);
|
||||
|
||||
/**
|
||||
* Return the list of {@link MediaType} objects supported by this converter.
|
||||
* @return the list of supported media types
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of <see cref="MediaType"/> objects supported by this converter.
|
||||
/// </summary>
|
||||
IList<MediaType> SupportedMediaTypes { get; }
|
||||
|
||||
/**
|
||||
* Read an object of the given type form the given input message, and returns it.
|
||||
* @param clazz the type of object to return. This type must have previously been passed to the
|
||||
* {@link #canRead canRead} method of this interface, which must have returned {@code true}.
|
||||
* @param inputMessage the HTTP input message to read from
|
||||
* @return the converted object
|
||||
* @throws IOException in case of I/O errors
|
||||
* @throws HttpMessageNotReadableException in case of conversion errors
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Read an object of the given type form the given HTTP response, and returns it.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
/// The type of object to return. This type must have previously been passed to the
|
||||
/// <see cref="M:CanRead"/> method of this interface, which must have returned <see langword="true"/>.
|
||||
/// </typeparam>
|
||||
/// <param name="response">The HTTP response to read from.</param>
|
||||
/// <returns>The converted object.</returns>
|
||||
T Read<T>(HttpWebResponse response) where T : class;
|
||||
|
||||
/**
|
||||
* Write an given object to the given output message.
|
||||
* @param t the object to write to the output message. The type of this object must have previously been
|
||||
* passed to the {@link #canWrite canWrite} method of this interface, which must have returned {@code true}.
|
||||
* @param contentType the content type to use when writing. May be {@code null} to indicate that the
|
||||
* default content type of the converter must be used. If not {@code null}, this media type must have
|
||||
* previously been passed to the {@link #canWrite canWrite} method of this interface, which must have
|
||||
* returned {@code true}.
|
||||
* @param outputMessage the message to write to
|
||||
* @throws IOException in case of I/O errors
|
||||
* @throws HttpMessageNotWritableException in case of conversion errors
|
||||
*/
|
||||
/// <summary>
|
||||
/// Write an given object to the given HTTP request.
|
||||
/// </summary>
|
||||
/// <param name="content">
|
||||
/// The object to write to the HTTP request. The type of this object must have previously been
|
||||
/// passed to the <see cref="M:CanWrite"/> method of this interface, which must have returned <see langword="true"/>.
|
||||
/// </param>
|
||||
/// <param name="mediaType">
|
||||
/// The content type to use when writing. May be null to indicate that the default content type of the converter must be used.
|
||||
/// If not null, this media type must have previously been passed to the <see cref="M:CanWrite"/> method of this interface,
|
||||
/// which must have returned <see langword="true"/>.
|
||||
/// </param>
|
||||
/// <param name="request">The HTTP request to write to.</param>
|
||||
void Write(object content, MediaType mediaType, HttpWebRequest request);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,20 +31,48 @@ using Spring.Util;
|
||||
namespace Spring.Http.Converters.Json
|
||||
{
|
||||
// TODO : Support for known types, etc...
|
||||
// TODO : Fix Write method
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="IHttpMessageConverter"/> that can read and write JSON.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default, this converter supports 'application/json' media type.
|
||||
/// This can be overridden by setting the <see cref="P:SupportedMediaTypes"/> property.
|
||||
/// </remarks>
|
||||
/// <author>Bruno Baia</author>
|
||||
public class JsonHttpMessageConverter : AbstractHttpMessageConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Default encoding for JSON.
|
||||
/// </summary>
|
||||
public static readonly Encoding DEFAULT_CHARSET = Encoding.UTF8;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="JsonHttpMessageConverter"/>
|
||||
/// with the media type 'application/json'.
|
||||
/// </summary>
|
||||
public JsonHttpMessageConverter() :
|
||||
base(new MediaType("application", "json"))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the given class is supported by this converter.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to test for support.</param>
|
||||
/// <returns><see langword="true"/> if supported; otherwise <see langword="false"/></returns>
|
||||
protected override bool Supports(Type type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract template method that reads the actualy object. Invoked from <see cref="M:Read"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object to return.</typeparam>
|
||||
/// <param name="response">The HTTP response to read from.</param>
|
||||
/// <returns>The converted object.</returns>
|
||||
protected override T ReadInternal<T>(HttpWebResponse response)
|
||||
{
|
||||
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
|
||||
@@ -54,12 +82,17 @@ namespace Spring.Http.Converters.Json
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract template method that writes the actual body. Invoked from <see cref="M:Write"/>.
|
||||
/// </summary>
|
||||
/// <param name="content">The object to write to the HTTP request.</param>
|
||||
/// <param name="request">The HTTP request to write to.</param>
|
||||
protected override void WriteInternal(object content, HttpWebRequest request)
|
||||
{
|
||||
// Get the request encoding
|
||||
MediaType mediaType = MediaType.ParseMediaType(request.Headers[HttpRequestHeader.ContentType]);
|
||||
MediaType mediaType = MediaType.ParseMediaType(request.ContentType);
|
||||
Encoding encoding;
|
||||
if (mediaType == null || String.IsNullOrEmpty(mediaType.CharSet))
|
||||
if (mediaType == null || !StringUtils.HasText(mediaType.CharSet))
|
||||
{
|
||||
encoding = DEFAULT_CHARSET;
|
||||
}
|
||||
@@ -70,18 +103,19 @@ namespace Spring.Http.Converters.Json
|
||||
|
||||
DataContractJsonSerializer serializer = new DataContractJsonSerializer(content.GetType());
|
||||
|
||||
// Write data
|
||||
using (Stream postStream = request.GetRequestStream())
|
||||
// Write to the request
|
||||
using (IgnoreCloseMemoryStream requestStream = new IgnoreCloseMemoryStream())
|
||||
{
|
||||
using (XmlDictionaryWriter jsonWriter = JsonReaderWriterFactory.CreateJsonWriter(postStream, encoding, false))
|
||||
using (XmlDictionaryWriter jsonWriter = JsonReaderWriterFactory.CreateJsonWriter(requestStream, encoding, false))
|
||||
{
|
||||
serializer.WriteObject(jsonWriter, content);
|
||||
jsonWriter.Flush();
|
||||
}
|
||||
postStream.Flush();
|
||||
|
||||
|
||||
// Set the content length in the request headers
|
||||
request.ContentLength = postStream.Length;
|
||||
request.ContentLength = requestStream.Length;
|
||||
|
||||
requestStream.CopyToAndClose(request.GetRequestStream());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,37 +23,57 @@ using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Http.Converters
|
||||
{
|
||||
/**
|
||||
* Implementation of {@link HttpMessageConverter} that can read and write strings.
|
||||
*
|
||||
* <p>By default, this converter supports all media types (<code>*/*</code>), and writes with a {@code
|
||||
* Content-Type} of {@code text/plain}. This can be overridden by setting the {@link
|
||||
* #setSupportedMediaTypes(java.util.List) supportedMediaTypes} property.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="IHttpMessageConverter"/> that can read and write strings.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default, this converter supports all media types '*/*', and writes with a 'Content-Type'
|
||||
/// of 'text/plain'.
|
||||
/// This can be overridden by setting the <see cref="P:SupportedMediaTypes"/> property.
|
||||
/// </remarks>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
public class StringHttpMessageConverter : AbstractHttpMessageConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Default encoding for strings.
|
||||
/// </summary>
|
||||
public static readonly Encoding DEFAULT_CHARSET = Encoding.GetEncoding("ISO-8859-1");
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="ByteArrayHttpMessageConverter"/>
|
||||
/// with 'text/plain; charset=ISO-8859-1', and '*/*' media types.
|
||||
/// </summary>
|
||||
public StringHttpMessageConverter() :
|
||||
base(new MediaType("text", "plain", "ISO-8859-1"), MediaType.ALL)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the given class is supported by this converter.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to test for support.</param>
|
||||
/// <returns><see langword="true"/> if supported; otherwise <see langword="false"/></returns>
|
||||
protected override bool Supports(Type type)
|
||||
{
|
||||
return type.Equals(typeof(string));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract template method that reads the actualy object. Invoked from <see cref="M:Read"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object to return.</typeparam>
|
||||
/// <param name="response">The HTTP response to read from.</param>
|
||||
/// <returns>The converted object.</returns>
|
||||
protected override T ReadInternal<T>(HttpWebResponse response)
|
||||
{
|
||||
// Get the response encoding
|
||||
Encoding encoding;
|
||||
if (String.IsNullOrEmpty(response.CharacterSet))
|
||||
if (!StringUtils.HasText(response.CharacterSet))
|
||||
{
|
||||
encoding = DEFAULT_CHARSET;
|
||||
}
|
||||
@@ -69,12 +89,17 @@ namespace Spring.Http.Converters
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract template method that writes the actual body. Invoked from <see cref="M:Write"/>.
|
||||
/// </summary>
|
||||
/// <param name="content">The object to write to the HTTP request.</param>
|
||||
/// <param name="request">The HTTP request to write to.</param>
|
||||
protected override void WriteInternal(object content, HttpWebRequest request)
|
||||
{
|
||||
// Get the request encoding
|
||||
MediaType mediaType = MediaType.ParseMediaType(request.Headers[HttpRequestHeader.ContentType]);
|
||||
Encoding encoding;
|
||||
if (mediaType == null || String.IsNullOrEmpty(mediaType.CharSet))
|
||||
MediaType mediaType = MediaType.ParseMediaType(request.ContentType);
|
||||
if (mediaType == null || !StringUtils.HasText(mediaType.CharSet))
|
||||
{
|
||||
encoding = DEFAULT_CHARSET;
|
||||
}
|
||||
@@ -89,7 +114,7 @@ namespace Spring.Http.Converters
|
||||
// Set the content length in the request headers
|
||||
request.ContentLength = byteData.Length;
|
||||
|
||||
// Write data
|
||||
// Write to the request
|
||||
using (Stream postStream = request.GetRequestStream())
|
||||
{
|
||||
postStream.Write(byteData, 0, byteData.Length);
|
||||
|
||||
@@ -18,20 +18,36 @@
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Http.Converters.Xml
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for <see cref="IHttpMessageConverter"/> that convert from/to XML.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default, subclasses of this converter support 'text/xml', 'application/xml', and 'application/*-xml' media types.
|
||||
/// This can be overridden by setting the <see cref="P:SupportedMediaTypes"/> property.
|
||||
/// </remarks>
|
||||
/// <author>Bruno Baia</author>
|
||||
public abstract class AbstractXmlHttpMessageConverter : AbstractHttpMessageConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Default encoding for XML.
|
||||
/// </summary>
|
||||
public static readonly Encoding DEFAULT_CHARSET = Encoding.UTF8;
|
||||
|
||||
private XmlReaderSettings _xmlReaderSettings;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="XmlReaderSettings">XmlReader settings</see>
|
||||
/// used by this converter to read from the HTTP response.
|
||||
/// </summary>
|
||||
public XmlReaderSettings XmlReaderSettings
|
||||
{
|
||||
get
|
||||
@@ -45,15 +61,31 @@ namespace Spring.Http.Converters.Xml
|
||||
set { _xmlReaderSettings = value; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an {@code AbstractHttpMessageConverter} with multiple supported media type.
|
||||
* @param supportedMediaTypes the supported media types
|
||||
*/
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="AbstractHttpMessageConverter"/>
|
||||
/// with multiple supported media type.
|
||||
/// </summary>
|
||||
/// <param name="supportedMediaTypes">The supported media types.</param>
|
||||
protected AbstractXmlHttpMessageConverter(params MediaType[] supportedMediaTypes) :
|
||||
base(supportedMediaTypes)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="AbstractHttpMessageConverter"/> that sets
|
||||
/// the <see cref="P:SupportedMediaTypes"/> to 'text/xml' and 'application/xml', and 'application/*-xml'.
|
||||
/// </summary>
|
||||
protected AbstractXmlHttpMessageConverter() :
|
||||
base(new MediaType("application", "xml"), new MediaType("text", "xml"), new MediaType("application", "*+xml"))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract template method that reads the actualy object. Invoked from <see cref="M:Read"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object to return.</typeparam>
|
||||
/// <param name="response">The HTTP response to read from.</param>
|
||||
/// <returns>The converted object.</returns>
|
||||
protected override T ReadInternal<T>(HttpWebResponse response)
|
||||
{
|
||||
using (Stream stream = response.GetResponseStream())
|
||||
@@ -65,12 +97,17 @@ namespace Spring.Http.Converters.Xml
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract template method that writes the actual body. Invoked from <see cref="M:Write"/>.
|
||||
/// </summary>
|
||||
/// <param name="content">The object to write to the HTTP request.</param>
|
||||
/// <param name="request">The HTTP request to write to.</param>
|
||||
protected override void WriteInternal(object content, HttpWebRequest request)
|
||||
{
|
||||
// Get the request encoding
|
||||
MediaType mediaType = MediaType.ParseMediaType(request.Headers[HttpRequestHeader.ContentType]);
|
||||
Encoding encoding;
|
||||
if (mediaType == null || String.IsNullOrEmpty(mediaType.CharSet))
|
||||
MediaType mediaType = MediaType.ParseMediaType(request.ContentType);
|
||||
if (mediaType == null || !StringUtils.HasText(mediaType.CharSet))
|
||||
{
|
||||
encoding = DEFAULT_CHARSET;
|
||||
}
|
||||
@@ -79,20 +116,44 @@ namespace Spring.Http.Converters.Xml
|
||||
encoding = Encoding.GetEncoding(mediaType.CharSet);
|
||||
}
|
||||
|
||||
using (Stream postStream = request.GetRequestStream())
|
||||
// Write to the request
|
||||
using (IgnoreCloseMemoryStream requestStream = new IgnoreCloseMemoryStream())
|
||||
{
|
||||
using (XmlTextWriter xmlWriter = new XmlTextWriter(postStream, encoding))
|
||||
using (XmlTextWriter xmlWriter = new XmlTextWriter(requestStream, encoding))
|
||||
{
|
||||
WriteXml(xmlWriter, content, request);
|
||||
xmlWriter.Flush();
|
||||
}
|
||||
|
||||
// TODO : Don't work
|
||||
// Set the content length in the request headers
|
||||
request.ContentLength = postStream.Length;
|
||||
request.ContentLength = requestStream.Length;
|
||||
|
||||
requestStream.CopyToAndClose(request.GetRequestStream());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract template method that reads the actualy object using a <see cref="XmlReader"/>. Invoked from <see cref="M:ReadInternal"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object to return.</typeparam>
|
||||
/// <param name="xmlReader">The XmlReader to use.</param>
|
||||
/// <param name="response">The HTTP response to read from.</param>
|
||||
/// <returns>The converted object.</returns>
|
||||
protected abstract T ReadXml<T>(XmlReader xmlReader, HttpWebResponse response) where T : class;
|
||||
|
||||
/// <summary>
|
||||
/// Abstract template method that writes the actual body using a <see cref="XmlWriter"/>. Invoked from <see cref="M:WriteInternal"/>.
|
||||
/// </summary>
|
||||
/// <param name="xmlWriter">The XmlWriter to use.</param>
|
||||
/// <param name="content">The object to write to the HTTP request.</param>
|
||||
/// <param name="request">The HTTP request to write to.</param>
|
||||
protected abstract void WriteXml(XmlWriter xmlWriter, object content, HttpWebRequest request);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the default <see cref="XmlReaderSettings">XmlReader settings</see>
|
||||
/// used by this converter to read from the HTTP response.
|
||||
/// </summary>
|
||||
/// <returns>The XmlReader settings.</returns>
|
||||
protected virtual XmlReaderSettings GetDefaultXmlReaderSettings()
|
||||
{
|
||||
XmlReaderSettings settings = new XmlReaderSettings();
|
||||
@@ -102,9 +163,5 @@ namespace Spring.Http.Converters.Xml
|
||||
settings.IgnoreWhitespace = true;
|
||||
return settings;
|
||||
}
|
||||
|
||||
protected abstract T ReadXml<T>(XmlReader xmlReader, HttpWebResponse response) where T : class;
|
||||
|
||||
protected abstract void WriteXml(XmlWriter xmlWriter, object content, HttpWebRequest request);
|
||||
}
|
||||
}
|
||||
@@ -26,67 +26,72 @@ using System.Xml;
|
||||
using System.Text;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Http.Converters.Xml
|
||||
{
|
||||
// TODO : Derive from AbstractXmlHttpMessageConverter ?
|
||||
// TODO : Support for known types, etc...
|
||||
public class DataContractHttpMessageConverter : AbstractHttpMessageConverter
|
||||
{
|
||||
public static readonly Encoding DEFAULT_CHARSET = Encoding.UTF8;
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="IHttpMessageConverter"/> that can read and write XML
|
||||
/// using <see cref="DataContractSerializer"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// By default, this converter supports 'text/xml', 'application/xml', and 'application/*-xml' media types.
|
||||
/// This can be overridden by setting the <see cref="P:SupportedMediaTypes"/> property.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This converter can read classes annotated with <see cref="DataContractAttribute"/> and <see cref="CollectionDataContractAttribute"/>, and write classes
|
||||
/// annotated with with {@link XmlRootElement}, or subclasses thereof.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <author>Bruno Baia</author>
|
||||
public class DataContractHttpMessageConverter : AbstractXmlHttpMessageConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="DataContractHttpMessageConverter"/>
|
||||
/// with 'text/xml', 'application/xml', and 'application/*-xml' media types.
|
||||
/// </summary>
|
||||
public DataContractHttpMessageConverter() :
|
||||
base(new MediaType("application", "xml"), new MediaType("text", "xml"), new MediaType("application", "*+xml"))
|
||||
base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the given class is supported by this converter.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to test for support.</param>
|
||||
/// <returns><see langword="true"/> if supported; otherwise <see langword="false"/></returns>
|
||||
protected override bool Supports(Type type)
|
||||
{
|
||||
return true;
|
||||
//return (
|
||||
// AttributeUtils.FindAttribute(type, typeof(DataContractAttribute)) != null ||
|
||||
// AttributeUtils.FindAttribute(type, typeof(SerializableAttribute)) != null ||
|
||||
// typeof(ISerializable).IsAssignableFrom(type));
|
||||
return (
|
||||
Attribute.GetCustomAttributes(type, typeof(DataContractAttribute), true).Length > 0 ||
|
||||
Attribute.GetCustomAttributes(type, typeof(CollectionDataContractAttribute), true).Length > 0
|
||||
);
|
||||
}
|
||||
|
||||
protected override T ReadInternal<T>(HttpWebResponse response)
|
||||
/// <summary>
|
||||
/// Abstract template method that reads the actualy object using a <see cref="XmlReader"/>. Invoked from <see cref="M:ReadInternal"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object to return.</typeparam>
|
||||
/// <param name="xmlReader">The XmlReader to use.</param>
|
||||
/// <param name="response">The HTTP response to read from.</param>
|
||||
/// <returns>The converted object.</returns>
|
||||
protected override T ReadXml<T>(XmlReader xmlReader, HttpWebResponse response)
|
||||
{
|
||||
DataContractSerializer serializer = new DataContractSerializer(typeof(T));
|
||||
using (Stream stream = response.GetResponseStream())
|
||||
{
|
||||
return (T)serializer.ReadObject(stream) as T;
|
||||
}
|
||||
return serializer.ReadObject(xmlReader) as T;
|
||||
}
|
||||
|
||||
protected override void WriteInternal(object content, HttpWebRequest request)
|
||||
/// <summary>
|
||||
/// Abstract template method that writes the actual body using a <see cref="XmlWriter"/>. Invoked from <see cref="M:WriteInternal"/>.
|
||||
/// </summary>
|
||||
/// <param name="xmlWriter">The XmlWriter to use.</param>
|
||||
/// <param name="content">The object to write to the HTTP request.</param>
|
||||
/// <param name="request">The HTTP request to write to.</param>
|
||||
protected override void WriteXml(XmlWriter xmlWriter, object content, HttpWebRequest request)
|
||||
{
|
||||
// Get the request encoding
|
||||
MediaType mediaType = MediaType.ParseMediaType(request.Headers[HttpRequestHeader.ContentType]);
|
||||
Encoding encoding;
|
||||
if (mediaType == null || String.IsNullOrEmpty(mediaType.CharSet))
|
||||
{
|
||||
encoding = DEFAULT_CHARSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
encoding = Encoding.GetEncoding(mediaType.CharSet);
|
||||
}
|
||||
|
||||
DataContractSerializer serializer = new DataContractSerializer(content.GetType());
|
||||
|
||||
// Write data
|
||||
using (Stream postStream = request.GetRequestStream())
|
||||
{
|
||||
using (XmlTextWriter xmlWriter = new XmlTextWriter(postStream, encoding))
|
||||
{
|
||||
serializer.WriteObject(xmlWriter, content);
|
||||
xmlWriter.Flush();
|
||||
}
|
||||
|
||||
// Set the content length in the request headers
|
||||
request.ContentLength = postStream.Length;
|
||||
}
|
||||
serializer.WriteObject(xmlWriter, content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,23 +27,55 @@ using System.Xml.Linq;
|
||||
namespace Spring.Http.Converters.Xml
|
||||
{
|
||||
// TODO : Support XElement.Load options
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="IHttpMessageConverter"/> that can read and write XML
|
||||
/// from a <see cref="XElement"/> (Linq to XML).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default, this converter supports 'text/xml', 'application/xml', and 'application/*-xml' media types.
|
||||
/// This can be overridden by setting the <see cref="P:SupportedMediaTypes"/> property.
|
||||
/// </remarks>
|
||||
/// <author>Bruno Baia</author>
|
||||
public class XElementHttpMessageConverter : AbstractXmlHttpMessageConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="XElementHttpMessageConverter"/>
|
||||
/// with 'text/xml', 'application/xml', and 'application/*-xml' media types.
|
||||
/// </summary>
|
||||
public XElementHttpMessageConverter() :
|
||||
base(new MediaType("application", "xml"), new MediaType("text", "xml"), new MediaType("application", "*+xml"))
|
||||
base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the given class is supported by this converter.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to test for support.</param>
|
||||
/// <returns><see langword="true"/> if supported; otherwise <see langword="false"/></returns>
|
||||
protected override bool Supports(Type type)
|
||||
{
|
||||
return type.Equals(typeof(XElement));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract template method that reads the actualy object using a <see cref="XmlReader"/>. Invoked from <see cref="M:ReadInternal"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object to return.</typeparam>
|
||||
/// <param name="xmlReader">The XmlReader to use.</param>
|
||||
/// <param name="response">The HTTP response to read from.</param>
|
||||
/// <returns>The converted object.</returns>
|
||||
protected override T ReadXml<T>(XmlReader xmlReader, HttpWebResponse response)
|
||||
{
|
||||
return XElement.Load(xmlReader) as T;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract template method that writes the actual body using a <see cref="XmlWriter"/>. Invoked from <see cref="M:WriteInternal"/>.
|
||||
/// </summary>
|
||||
/// <param name="xmlWriter">The XmlWriter to use.</param>
|
||||
/// <param name="content">The object to write to the HTTP request.</param>
|
||||
/// <param name="request">The HTTP request to write to.</param>
|
||||
protected override void WriteXml(XmlWriter xmlWriter, object content, HttpWebRequest request)
|
||||
{
|
||||
XElement xElement = content as XElement;
|
||||
|
||||
@@ -24,18 +24,43 @@ using System.Net;
|
||||
|
||||
namespace Spring.Http.Converters.Xml
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="IHttpMessageConverter"/> that can read and write XML
|
||||
/// from a <see cref="XmlDocument"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default, this converter supports 'text/xml', 'application/xml', and 'application/*-xml' media types.
|
||||
/// This can be overridden by setting the <see cref="P:SupportedMediaTypes"/> property.
|
||||
/// </remarks>
|
||||
/// <author>Bruno Baia</author>
|
||||
public class XmlDocumentHttpMessageConverter : AbstractXmlHttpMessageConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="XmlDocumentHttpMessageConverter"/>
|
||||
/// with 'text/xml', 'application/xml', and 'application/*-xml' media types.
|
||||
/// </summary>
|
||||
public XmlDocumentHttpMessageConverter() :
|
||||
base(new MediaType("application", "xml"), new MediaType("text", "xml"), new MediaType("application", "*+xml"))
|
||||
base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the given class is supported by this converter.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to test for support.</param>
|
||||
/// <returns><see langword="true"/> if supported; otherwise <see langword="false"/></returns>
|
||||
protected override bool Supports(Type type)
|
||||
{
|
||||
return type.Equals(typeof(XmlDocument));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract template method that reads the actualy object using a <see cref="XmlReader"/>. Invoked from <see cref="M:ReadInternal"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object to return.</typeparam>
|
||||
/// <param name="xmlReader">The XmlReader to use.</param>
|
||||
/// <param name="response">The HTTP response to read from.</param>
|
||||
/// <returns>The converted object.</returns>
|
||||
protected override T ReadXml<T>(XmlReader xmlReader, HttpWebResponse response)
|
||||
{
|
||||
XmlDocument document = new XmlDocument();
|
||||
@@ -43,6 +68,12 @@ namespace Spring.Http.Converters.Xml
|
||||
return document as T;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract template method that writes the actual body using a <see cref="XmlWriter"/>. Invoked from <see cref="M:WriteInternal"/>.
|
||||
/// </summary>
|
||||
/// <param name="xmlWriter">The XmlWriter to use.</param>
|
||||
/// <param name="content">The object to write to the HTTP request.</param>
|
||||
/// <param name="request">The HTTP request to write to.</param>
|
||||
protected override void WriteXml(XmlWriter xmlWriter, object content, HttpWebRequest request)
|
||||
{
|
||||
XmlDocument document = content as XmlDocument;
|
||||
|
||||
@@ -23,18 +23,35 @@ using System.Xml;
|
||||
using System.Net;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Http.Converters.Xml
|
||||
{
|
||||
// TODO : Support for known types, etc...
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="IHttpMessageConverter"/> that can read and write XML
|
||||
/// using <see cref="XmlSerializer"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default, this converter supports 'text/xml', 'application/xml', and 'application/*-xml' media types.
|
||||
/// This can be overridden by setting the <see cref="P:SupportedMediaTypes"/> property.
|
||||
/// </remarks>
|
||||
/// <author>Bruno Baia</author>
|
||||
public class XmlSerializableHttpMessageConverter : AbstractXmlHttpMessageConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="XmlSerializableHttpMessageConverter"/>
|
||||
/// with 'text/xml', 'application/xml', and 'application/*-xml' media types.
|
||||
/// </summary>
|
||||
public XmlSerializableHttpMessageConverter() :
|
||||
base(new MediaType("application", "xml"), new MediaType("text", "xml"), new MediaType("application", "*+xml"))
|
||||
base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the given class is supported by this converter.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to test for support.</param>
|
||||
/// <returns><see langword="true"/> if supported; otherwise <see langword="false"/></returns>
|
||||
protected override bool Supports(Type type)
|
||||
{
|
||||
return true;
|
||||
@@ -43,12 +60,25 @@ namespace Spring.Http.Converters.Xml
|
||||
// AttributeUtils.FindAttribute(type, typeof(XmlTypeAttribute)) != null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract template method that reads the actualy object using a <see cref="XmlReader"/>. Invoked from <see cref="M:ReadInternal"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object to return.</typeparam>
|
||||
/// <param name="xmlReader">The XmlReader to use.</param>
|
||||
/// <param name="response">The HTTP response to read from.</param>
|
||||
/// <returns>The converted object.</returns>
|
||||
protected override T ReadXml<T>(XmlReader xmlReader, HttpWebResponse response)
|
||||
{
|
||||
XmlSerializer serializer = new XmlSerializer(typeof(T));
|
||||
return serializer.Deserialize(xmlReader) as T;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract template method that writes the actual body using a <see cref="XmlWriter"/>. Invoked from <see cref="M:WriteInternal"/>.
|
||||
/// </summary>
|
||||
/// <param name="xmlWriter">The XmlWriter to use.</param>
|
||||
/// <param name="content">The object to write to the HTTP request.</param>
|
||||
/// <param name="request">The HTTP request to write to.</param>
|
||||
protected override void WriteXml(XmlWriter xmlWriter, object content, HttpWebRequest request)
|
||||
{
|
||||
XmlSerializer serializer = new XmlSerializer(content.GetType());
|
||||
|
||||
@@ -24,13 +24,11 @@ using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace Spring.Http
|
||||
{
|
||||
/**
|
||||
* Factory for {@link ClientHttpRequest} objects.
|
||||
* Requests are created by the {@link #createRequest(URI, HttpMethod)} method.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
/// <summary>
|
||||
/// Factory for <see cref="HttpWebRequest"/> objects. Requests are created by the <see cref="M:CreateRequest"/> method.
|
||||
/// </summary>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
public class DefaultHttpWebRequestFactory : IHttpWebRequestFactory
|
||||
{
|
||||
// TODO : Add other properties
|
||||
@@ -40,6 +38,9 @@ namespace Spring.Http
|
||||
private IWebProxy _proxy;
|
||||
private int? _timeout;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the collection of security certificates that are associated with this request.
|
||||
/// </summary>
|
||||
public X509CertificateCollection ClientCertificates
|
||||
{
|
||||
get
|
||||
@@ -52,18 +53,34 @@ namespace Spring.Http
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets authentication information for the request.
|
||||
/// </summary>
|
||||
public ICredentials Credentials
|
||||
{
|
||||
get { return _credentials; }
|
||||
set { _credentials = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets proxy information for the request.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The default value is set by calling the <see cref="P:System.Net.GlobalProxySelection.Select"/> property.
|
||||
/// </remarks>
|
||||
public IWebProxy Proxy
|
||||
{
|
||||
get { return _proxy; }
|
||||
set { _proxy = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time-out value in milliseconds for the <see cref="M:System.Net.HttpWebRequest.GetResponse()"/>
|
||||
/// and <see cref="M:System.Net.HttpWebRequest.GetRequestStream()"/> methods.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The default is 100,000 milliseconds (100 seconds).
|
||||
/// </remarks>
|
||||
public int? Timeout
|
||||
{
|
||||
get { return _timeout; }
|
||||
@@ -72,15 +89,11 @@ namespace Spring.Http
|
||||
|
||||
#region IHttpWebRequestFactory Membres
|
||||
|
||||
/**
|
||||
* Create a new {@link ClientHttpRequest} for the specified URI and HTTP method.
|
||||
* <p>The returned request can be written to, and then executed by calling
|
||||
* {@link ClientHttpRequest#execute()}.
|
||||
* @param uri the URI to create a request for
|
||||
* @param httpMethod the HTTP method to execute
|
||||
* @return the created request
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
/// <summary>
|
||||
/// Create a new <see cref="HttpWebRequest"/> for the specified URI.
|
||||
/// </summary>
|
||||
/// <param name="uri">The URI to create a request for.</param>
|
||||
/// <returns>The created request</returns>
|
||||
public HttpWebRequest CreateRequest(Uri uri)
|
||||
{
|
||||
HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest;
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
@@ -22,23 +22,52 @@ using System;
|
||||
|
||||
namespace Spring.Http
|
||||
{
|
||||
/**
|
||||
* Java 5 enumeration of HTTP request methods. Intended for use
|
||||
* with {@link org.springframework.http.client.ClientHttpRequest}
|
||||
* and {@link org.springframework.web.client.RestTemplate}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
/// <summary>
|
||||
/// Enumeration of HTTP request methods as defined in the HTTP specification.
|
||||
/// <a href="http://tools.ietf.org/html/rfc2616#section-5.1.1">HTTP 1.1, section 6</a>
|
||||
/// </summary>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Bruno Baia</author>
|
||||
public enum HttpMethod
|
||||
{
|
||||
/// <summary>
|
||||
/// The OPTIONS method.
|
||||
/// </summary>
|
||||
OPTIONS,
|
||||
|
||||
/// <summary>
|
||||
/// The GET method.
|
||||
/// </summary>
|
||||
GET,
|
||||
HEAD,
|
||||
POST,
|
||||
PUT,
|
||||
DELETE,
|
||||
|
||||
/// <summary>
|
||||
/// The HEAD method.
|
||||
/// </summary>
|
||||
HEAD,
|
||||
|
||||
/// <summary>
|
||||
/// The POST method.
|
||||
/// </summary>
|
||||
POST,
|
||||
|
||||
/// <summary>
|
||||
/// The PUT method.
|
||||
/// </summary>
|
||||
PUT,
|
||||
|
||||
/// <summary>
|
||||
/// The DELETE method.
|
||||
/// </summary>
|
||||
DELETE,
|
||||
|
||||
/// <summary>
|
||||
/// The TRACE method.
|
||||
/// </summary>
|
||||
TRACE,
|
||||
|
||||
/// <summary>
|
||||
/// The CONNECT method.
|
||||
/// </summary>
|
||||
CONNECT
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,11 @@ using System.Net;
|
||||
|
||||
namespace Spring.Http
|
||||
{
|
||||
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5
|
||||
/// <summary>
|
||||
/// Represents a HTTP request message, as defined in the HTTP specification.
|
||||
/// <a href="http://tools.ietf.org/html/rfc2616#section-5">HTTP 1.1, section 5</a>
|
||||
/// </summary>
|
||||
/// <author>Bruno Baia</author>
|
||||
public class HttpRequestMessage
|
||||
{
|
||||
//private string requestUri;
|
||||
@@ -43,87 +47,94 @@ namespace Spring.Http
|
||||
// set { httpVersion = value; }
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the HTTP method.
|
||||
/// </summary>
|
||||
public HttpMethod Method
|
||||
{
|
||||
get { return this.method; }
|
||||
set { this.method = value; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the headers of this message.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Gets the request headers.
|
||||
/// </summary>
|
||||
public WebHeaderCollection Headers
|
||||
{
|
||||
get { return this.headers; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the body of this message.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Gets the response body.
|
||||
/// </summary>
|
||||
public object Body
|
||||
{
|
||||
get { return this.body; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code HttpRequestMessage} with no body and no headers.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="HttpRequestMessage"/> with the given Http method.
|
||||
/// </summary>
|
||||
/// <param name="method">The HTTP method.</param>
|
||||
public HttpRequestMessage(HttpMethod method) :
|
||||
this(null, new WebHeaderCollection(), method)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code HttpRequestMessage} with the given headers and no body.
|
||||
* @param headers the message headers
|
||||
*/
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="HttpRequestMessage"/> with the given headers.
|
||||
/// </summary>
|
||||
/// <param name="headers">The request headers.</param>
|
||||
public HttpRequestMessage(WebHeaderCollection headers) :
|
||||
this(null, headers, HttpMethod.GET)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code HttpRequestMessage} with the given headers and no body.
|
||||
* @param headers the message headers
|
||||
*/
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="HttpRequestMessage"/> with the given headers and HTTP method.
|
||||
/// </summary>
|
||||
/// <param name="headers">The request headers.</param>
|
||||
/// <param name="method">The HTTP method.</param>
|
||||
public HttpRequestMessage(WebHeaderCollection headers, HttpMethod method) :
|
||||
this(null, headers, method)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code HttpRequestMessage} with the given body and no headers.
|
||||
* @param body the message body
|
||||
*/
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="HttpRequestMessage"/> with the given body.
|
||||
/// </summary>
|
||||
/// <param name="body">The response body.</param>
|
||||
public HttpRequestMessage(object body) :
|
||||
this(body, new WebHeaderCollection(), HttpMethod.GET)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code HttpRequestMessage} with the given body and no headers.
|
||||
* @param body the message body
|
||||
*/
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="HttpRequestMessage"/> with the given body and HTTP method.
|
||||
/// </summary>
|
||||
/// <param name="body">The response body.</param>
|
||||
/// <param name="method">The HTTP method.</param>
|
||||
public HttpRequestMessage(object body, HttpMethod method) :
|
||||
this(body, new WebHeaderCollection(), method)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code HttpRequestMessage} with the given body and headers.
|
||||
* @param body the messagae body
|
||||
* @param headers the message headers
|
||||
*/
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="HttpRequestMessage"/> with the given body and headers.
|
||||
/// </summary>
|
||||
/// <param name="body">The response body.</param>
|
||||
/// <param name="headers">The response headers.</param>
|
||||
public HttpRequestMessage(object body, WebHeaderCollection headers) :
|
||||
this(body, headers, HttpMethod.GET)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code HttpRequestMessage} with the given body and headers.
|
||||
* @param body the messagae body
|
||||
* @param headers the message headers
|
||||
*/
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="HttpRequestMessage"/> with the given body, headers and HTTP method.
|
||||
/// </summary>
|
||||
/// <param name="body">The response body.</param>
|
||||
/// <param name="headers">The response headers.</param>
|
||||
/// <param name="method">The HTTP method.</param>
|
||||
public HttpRequestMessage(object body, WebHeaderCollection headers, HttpMethod method)
|
||||
{
|
||||
this.method = method;
|
||||
|
||||
@@ -22,86 +22,31 @@ using System.Net;
|
||||
|
||||
namespace Spring.Http
|
||||
{
|
||||
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6
|
||||
public class HttpResponseMessage<T> where T : class
|
||||
/// <summary>
|
||||
/// Represents a HTTP response message with no entity.
|
||||
/// </summary>
|
||||
/// <author>Bruno Baia</author>
|
||||
public class HttpResponseMessage : HttpResponseMessage<object>
|
||||
{
|
||||
private WebHeaderCollection headers;
|
||||
private T body;
|
||||
private HttpStatusCode statusCode;
|
||||
private string statusDescription;
|
||||
|
||||
/**
|
||||
* Returns the headers of this entity.
|
||||
*/
|
||||
public WebHeaderCollection Headers
|
||||
{
|
||||
get { return this.headers; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the body of this entity.
|
||||
*/
|
||||
public T Body
|
||||
{
|
||||
get { return this.body; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the HTTP status code of the response.
|
||||
* @return the HTTP status as an HttpStatus enum value
|
||||
*/
|
||||
public HttpStatusCode StatusCode
|
||||
{
|
||||
get { return statusCode; }
|
||||
}
|
||||
|
||||
public string StatusDescription
|
||||
{
|
||||
get { return statusDescription; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code ResponseEntity} with the given status code, and no body, no headers.
|
||||
* @param body the entity body
|
||||
* @param statusCode the status code
|
||||
*/
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="HttpResponseMessage"/> with the given status code and status description.
|
||||
/// </summary>
|
||||
/// <param name="statusCode">The HTTP status code.</param>
|
||||
/// <param name="statusDescription">The HTTP status description.</param>
|
||||
public HttpResponseMessage(HttpStatusCode statusCode, string statusDescription) :
|
||||
this(null, null, statusCode, statusDescription)
|
||||
base(null, null, statusCode, statusDescription)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code ResponseEntity} with the given body and status code, and no headers.
|
||||
* @param body the entity body
|
||||
* @param statusCode the status code
|
||||
*/
|
||||
public HttpResponseMessage(T body, HttpStatusCode statusCode, string statusDescription) :
|
||||
this(body, null, statusCode, statusDescription)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code HttpEntity} with the given headers and status code, and no body.
|
||||
* @param headers the entity headers
|
||||
* @param statusCode the status code
|
||||
*/
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="HttpResponseMessage"/> with the given headers, status code and status description.
|
||||
/// </summary>
|
||||
/// <param name="headers">The response headers.</param>
|
||||
/// <param name="statusCode">The HTTP status code.</param>
|
||||
/// <param name="statusDescription">The HTTP status description.</param>
|
||||
public HttpResponseMessage(WebHeaderCollection headers, HttpStatusCode statusCode, string statusDescription) :
|
||||
this(null, headers, statusCode, statusDescription)
|
||||
base(null, headers, statusCode, statusDescription)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code HttpEntity} with the given body, headers, and status code.
|
||||
* @param body the entity body
|
||||
* @param headers the entity headers
|
||||
* @param statusCode the status code
|
||||
*/
|
||||
public HttpResponseMessage(T body, WebHeaderCollection headers, HttpStatusCode statusCode, string statusDescription)
|
||||
{
|
||||
this.statusCode = statusCode;
|
||||
this.statusDescription = statusDescription;
|
||||
this.body = body;
|
||||
this.headers = headers;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
117
src/Spring/Spring.Http/Http/HttpResponseMessage`1.cs
Normal file
117
src/Spring/Spring.Http/Http/HttpResponseMessage`1.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System.Net;
|
||||
|
||||
namespace Spring.Http
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a HTTP response message, as defined in the HTTP specification.
|
||||
/// <a href="http://tools.ietf.org/html/rfc2616#section-6">HTTP 1.1, section 6</a>
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the response body.</typeparam>
|
||||
/// <author>Bruno Baia</author>
|
||||
public class HttpResponseMessage<T> where T : class
|
||||
{
|
||||
private WebHeaderCollection headers;
|
||||
private T body;
|
||||
private HttpStatusCode statusCode;
|
||||
private string statusDescription;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the response headers.
|
||||
/// </summary>
|
||||
public WebHeaderCollection Headers
|
||||
{
|
||||
get { return this.headers; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the response body. May be null.
|
||||
/// </summary>
|
||||
public T Body
|
||||
{
|
||||
get { return this.body; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the HTTP status code of the response.
|
||||
/// </summary>
|
||||
public HttpStatusCode StatusCode
|
||||
{
|
||||
get { return statusCode; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the HTTP status description of the response.
|
||||
/// </summary>
|
||||
public string StatusDescription
|
||||
{
|
||||
get { return statusDescription; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="HttpResponseMessage{T}"/> with the given status code and status description.
|
||||
/// </summary>
|
||||
/// <param name="statusCode">The HTTP status code.</param>
|
||||
/// <param name="statusDescription">The HTTP status description.</param>
|
||||
public HttpResponseMessage(HttpStatusCode statusCode, string statusDescription) :
|
||||
this(null, null, statusCode, statusDescription)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="HttpResponseMessage{T}"/> with the given body, status code and status description.
|
||||
/// </summary>
|
||||
/// <param name="body">The response body.</param>
|
||||
/// <param name="statusCode">The HTTP status code.</param>
|
||||
/// <param name="statusDescription">The HTTP status description.</param>
|
||||
public HttpResponseMessage(T body, HttpStatusCode statusCode, string statusDescription) :
|
||||
this(body, null, statusCode, statusDescription)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="HttpResponseMessage{T}"/> with the given headers, status code and status description.
|
||||
/// </summary>
|
||||
/// <param name="headers">The response headers.</param>
|
||||
/// <param name="statusCode">The HTTP status code.</param>
|
||||
/// <param name="statusDescription">The HTTP status description.</param>
|
||||
public HttpResponseMessage(WebHeaderCollection headers, HttpStatusCode statusCode, string statusDescription) :
|
||||
this(null, headers, statusCode, statusDescription)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="HttpResponseMessage{T}"/> with the given body, headers, status code and status description.
|
||||
/// </summary>
|
||||
/// <param name="body">The response body.</param>
|
||||
/// <param name="headers">The response headers.</param>
|
||||
/// <param name="statusCode">The HTTP status code.</param>
|
||||
/// <param name="statusDescription">The HTTP status description.</param>
|
||||
public HttpResponseMessage(T body, WebHeaderCollection headers, HttpStatusCode statusCode, string statusDescription)
|
||||
{
|
||||
this.statusCode = statusCode;
|
||||
this.statusDescription = statusDescription;
|
||||
this.body = body;
|
||||
this.headers = headers;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,24 +23,18 @@ using System.Net;
|
||||
|
||||
namespace Spring.Http
|
||||
{
|
||||
/**
|
||||
* Factory for {@link ClientHttpRequest} objects.
|
||||
* Requests are created by the {@link #createRequest(URI, HttpMethod)} method.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
/// <summary>
|
||||
/// Factory for <see cref="HttpWebRequest"/> objects. Requests are created by the <see cref="M:CreateRequest"/> method.
|
||||
/// </summary>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
public interface IHttpWebRequestFactory
|
||||
{
|
||||
/**
|
||||
* Create a new {@link ClientHttpRequest} for the specified URI and HTTP method.
|
||||
* <p>The returned request can be written to, and then executed by calling
|
||||
* {@link ClientHttpRequest#execute()}.
|
||||
* @param uri the URI to create a request for
|
||||
* @param httpMethod the HTTP method to execute
|
||||
* @return the created request
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
/// <summary>
|
||||
/// Create a new <see cref="HttpWebRequest"/> for the specified URI.
|
||||
/// </summary>
|
||||
/// <param name="uri">The URI to create a request for.</param>
|
||||
/// <returns>The created request</returns>
|
||||
HttpWebRequest CreateRequest(Uri uri);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,88 +28,88 @@ using Spring.Util;
|
||||
|
||||
namespace Spring.Http
|
||||
{
|
||||
/**
|
||||
* Represents an Internet Media Type, as defined in the HTTP specification.
|
||||
*
|
||||
* <p>Consists of a {@linkplain #getType() type} and a {@linkplain #getSubtype() subtype}.
|
||||
* Also has functionality to parse media types from a string using {@link #parseMediaType(String)},
|
||||
* or multiple comma-separated media types using {@link #parseMediaTypes(String)}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2616#section-3.7">HTTP 1.1, section 3.7</a>
|
||||
*/
|
||||
/// <summary>
|
||||
/// Represents an Internet Media Type, as defined in the HTTP specification.
|
||||
/// <a href="http://tools.ietf.org/html/rfc2616#section-3.7">HTTP 1.1, section 3.7</a>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Consists of a <see cref="P:Type"/> and a <see cref="P:SubType"/>.
|
||||
/// Also has functionality to parse media types from a string using <see cref="M:ParseMediaType(string)"/>,
|
||||
/// or multiple comma-separated media types using <see cref="M:ParseMediaTypes(string)"/>.
|
||||
/// </remarks>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
public class MediaType : IComparable<MediaType>
|
||||
{
|
||||
/**
|
||||
* Public constant media type that includes all media ranges (i.e. <code>*/*</code>).
|
||||
*/
|
||||
/// <summary>
|
||||
/// Public constant media type that includes all media ranges (i.e. '*/*').
|
||||
/// </summary>
|
||||
public static readonly MediaType ALL = new MediaType("*", "*");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code application/atom+xml}.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Public constant media type for 'application/atom+xml'.
|
||||
/// </summary>
|
||||
public static readonly MediaType APPLICATION_ATOM_XML = new MediaType("application", "atom+xml");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code application/x-www-form-urlencoded}.
|
||||
* */
|
||||
/// <summary>
|
||||
/// Public constant media type for 'application/x-www-form-urlencoded'.
|
||||
/// </summary>
|
||||
public static readonly MediaType APPLICATION_FORM_URLENCODED = new MediaType("application", "x-www-form-urlencoded");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code application/json}.
|
||||
* */
|
||||
/// <summary>
|
||||
/// Public constant media type for 'application/json'.
|
||||
/// </summary>
|
||||
public static readonly MediaType APPLICATION_JSON = new MediaType("application", "json");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code application/octet-stream}.
|
||||
* */
|
||||
/// <summary>
|
||||
/// Public constant media type for 'application/octet-stream'.
|
||||
/// </summary>
|
||||
public static readonly MediaType APPLICATION_OCTET_STREAM = new MediaType("application", "octet-stream");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code application/xhtml+xml}.
|
||||
* */
|
||||
/// <summary>
|
||||
/// Public constant media type for 'application/xhtml+xml'.
|
||||
/// </summary>
|
||||
public static readonly MediaType APPLICATION_XHTML_XML = new MediaType("application", "xhtml+xml");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code image/gif}.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Public constant media type for 'image/gif'.
|
||||
/// </summary>
|
||||
public static readonly MediaType IMAGE_GIF = new MediaType("image", "gif");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code image/jpeg}.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Public constant media type for 'image/jpeg'.
|
||||
/// </summary>
|
||||
public static readonly MediaType IMAGE_JPEG = new MediaType("image", "jpeg");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code image/png}.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Public constant media type for 'image/png'.
|
||||
/// </summary>
|
||||
public static readonly MediaType IMAGE_PNG = new MediaType("image", "png");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code image/xml}.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Public constant media type for 'image/xml'.
|
||||
/// </summary>
|
||||
public static readonly MediaType APPLICATION_XML = new MediaType("application", "xml");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code multipart/form-data}.
|
||||
* */
|
||||
/// <summary>
|
||||
/// Public constant media type for 'multipart/form-data'.
|
||||
/// </summary>
|
||||
public static readonly MediaType MULTIPART_FORM_DATA = new MediaType("multipart", "form-data");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code text/html}.
|
||||
* */
|
||||
/// <summary>
|
||||
/// Public constant media type for 'text/html'.
|
||||
/// </summary>
|
||||
public static readonly MediaType TEXT_HTML = new MediaType("text", "html");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code text/plain}.
|
||||
* */
|
||||
/// <summary>
|
||||
/// Public constant media type for 'text/plain'.
|
||||
/// </summary>
|
||||
public static readonly MediaType TEXT_PLAIN = new MediaType("text", "plain");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code text/xml}.
|
||||
* */
|
||||
/// <summary>
|
||||
/// Public constant media type for 'text/xml'.
|
||||
/// </summary>
|
||||
public static readonly MediaType TEXT_XML = new MediaType("text", "xml");
|
||||
|
||||
|
||||
@@ -125,43 +125,41 @@ namespace Spring.Http
|
||||
|
||||
private IDictionary<string, string> parameters;
|
||||
|
||||
/**
|
||||
* Return the primary type.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Gets the primary type.
|
||||
/// </summary>
|
||||
public string Type
|
||||
{
|
||||
get { return this.type; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the subtype.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Gets the subtype.
|
||||
/// </summary>
|
||||
public string Subtype
|
||||
{
|
||||
get { return this.subtype; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether the {@linkplain #getType() type} is the wildcard character <code>*</code> or not.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Indicate whether the type is the wildcard character '*', or not.
|
||||
/// </summary>
|
||||
public bool IsWildcardType
|
||||
{
|
||||
get { return WILDCARD_TYPE == type; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether the {@linkplain #getSubtype() subtype} is the wildcard character <code>*</code> or not.
|
||||
* @return whether the subtype is <code>*</code>
|
||||
*/
|
||||
/// <summary>
|
||||
/// Indicate whether the subtype is the wildcard character '*', or not.
|
||||
/// </summary>
|
||||
public bool IsWildcardSubtype
|
||||
{
|
||||
get { return WILDCARD_TYPE == subtype; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the character set, as indicated by a <code>charset</code> parameter, if any.
|
||||
* @return the character set; or <code>null</code> if not available
|
||||
*/
|
||||
/// <summary>
|
||||
/// Gets the character set, as indicated by a 'charset' parameter, if any.
|
||||
/// </summary>
|
||||
public string CharSet
|
||||
{
|
||||
get
|
||||
@@ -174,11 +172,10 @@ namespace Spring.Http
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the quality value, as indicated by a <code>q</code> parameter, if any.
|
||||
* Defaults to <code>1.0</code>.
|
||||
* @return the quality factory
|
||||
*/
|
||||
/// <summary>
|
||||
/// Gets the quality value, as indicated by a 'q' parameter, if any.
|
||||
/// Defaults to '1.0'.
|
||||
/// </summary>
|
||||
public double QualityValue
|
||||
{
|
||||
get
|
||||
@@ -190,75 +187,68 @@ namespace Spring.Http
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link MediaType} for the given primary type.
|
||||
* <p>The {@linkplain #getSubtype() subtype} is set to <code>*</code>, parameters empty.
|
||||
* @param type the primary type
|
||||
* @throws IllegalArgumentException if any of the parameters contain illegal characters
|
||||
*/
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="MediaType"/> for the given primary type.
|
||||
/// The subtype is set to '*', parameters are empty.
|
||||
/// </summary>
|
||||
/// <param name="type">The primary type.</param>
|
||||
public MediaType(string type) :
|
||||
this(type, WILDCARD_TYPE)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link MediaType} for the given primary type and subtype.
|
||||
* <p>The parameters are empty.
|
||||
* @param type the primary type
|
||||
* @param subtype the subtype
|
||||
* @throws IllegalArgumentException if any of the parameters contain illegal characters
|
||||
*/
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="MediaType"/> for the given primary type and subtype.
|
||||
/// The parameters are empty.
|
||||
/// </summary>
|
||||
/// <param name="type">The primary type.</param>
|
||||
/// <param name="subtype">The subtype.</param>
|
||||
public MediaType(string type, string subtype) :
|
||||
this(type, subtype, new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link MediaType} for the given type, subtype, and character set.
|
||||
* @param type the primary type
|
||||
* @param subtype the subtype
|
||||
* @param charSet the character set
|
||||
* @throws IllegalArgumentException if any of the parameters contain illegal characters
|
||||
*/
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="MediaType"/> for the given primary type, subtype and character set.
|
||||
/// </summary>
|
||||
/// <param name="type">The primary type.</param>
|
||||
/// <param name="subtype">The subtype.</param>
|
||||
/// <param name="charSet">The character set</param>
|
||||
public MediaType(string type, string subtype, string charSet) :
|
||||
this(type, subtype)
|
||||
{
|
||||
this.parameters.Add(PARAM_CHARSET, charSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link MediaType} for the given type, subtype, and quality value.
|
||||
*
|
||||
* @param type the primary type
|
||||
* @param subtype the subtype
|
||||
* @param qualityValue the quality value
|
||||
* @throws IllegalArgumentException if any of the parameters contain illegal characters
|
||||
*/
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="MediaType"/> for the given primary type, subtype and quality value.
|
||||
/// </summary>
|
||||
/// <param name="type">The primary type.</param>
|
||||
/// <param name="subtype">The subtype.</param>
|
||||
/// <param name="qualityValue">The quality value</param>
|
||||
public MediaType(String type, String subtype, double qualityValue) :
|
||||
this(type, subtype)
|
||||
{
|
||||
this.parameters.Add(PARAM_QUALITY_FACTOR, qualityValue.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy-constructor that copies the type and subtype of the given {@link MediaType},
|
||||
* and allows for different parameter.
|
||||
* @param other the other media type
|
||||
* @param parameters the parameters, may be <code>null</code>
|
||||
* @throws IllegalArgumentException if any of the parameters contain illegal characters
|
||||
*/
|
||||
public MediaType(MediaType other, IDictionary<string, string> parameters) :
|
||||
this(other.Type, other.Subtype, parameters)
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="MediaType"/> by copying the type and subtype of the given MediaType,
|
||||
/// and allows for different parameter.
|
||||
/// </summary>
|
||||
/// <param name="otherMediaType">The other media type.</param>
|
||||
/// <param name="parameters">The parameters, may be null.</param>
|
||||
public MediaType(MediaType otherMediaType, IDictionary<string, string> parameters) :
|
||||
this(otherMediaType.Type, otherMediaType.Subtype, parameters)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link MediaType} for the given type, subtype, and parameters.
|
||||
* @param type the primary type
|
||||
* @param subtype the subtype
|
||||
* @param parameters the parameters, may be <code>null</code>
|
||||
* @throws IllegalArgumentException if any of the parameters contain illegal characters
|
||||
*/
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="MediaType"/> for the given primary type, subtype and parameters.
|
||||
/// </summary>
|
||||
/// <param name="type">The primary type.</param>
|
||||
/// <param name="subtype">The subtype.</param>
|
||||
/// <param name="parameters">The parameters, may be null.</param>
|
||||
public MediaType(string type, string subtype, IDictionary<string, string> parameters)
|
||||
{
|
||||
AssertUtils.ArgumentHasText(type, "'type' must not be empty");
|
||||
@@ -285,6 +275,15 @@ namespace Spring.Http
|
||||
//}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
|
||||
/// </summary>
|
||||
/// <param name="obj">
|
||||
/// The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
|
||||
/// </returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
@@ -314,6 +313,15 @@ namespace Spring.Http
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serves as a hash function for a particular type.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="M:System.Object.GetHashCode"/> is suitable for use in hashing algorithms and data structures like a hash table.
|
||||
/// </remarks>
|
||||
/// <returns>
|
||||
/// A hash code for the current <see cref="T:System.Object"/>.
|
||||
/// </returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
int result = this.type.GetHashCode();
|
||||
@@ -322,6 +330,12 @@ namespace Spring.Http
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object."/>
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object."/>.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
@@ -338,11 +352,11 @@ namespace Spring.Http
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the given token string for illegal characters, as defined in RFC 2616, section 2.2.
|
||||
* @throws IllegalArgumentException in case of illegal characters
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2616#section-2.2">HTTP 1.1, section 2.2</a>
|
||||
*/
|
||||
// **
|
||||
// * Checks the given token string for illegal characters, as defined in RFC 2616, section 2.2.
|
||||
// * @throws IllegalArgumentException in case of illegal characters
|
||||
// * @see <a href="http://tools.ietf.org/html/rfc2616#section-2.2">HTTP 1.1, section 2.2</a>
|
||||
// */
|
||||
//private void checkToken(String s) {
|
||||
// for (int i=0; i < s.length(); i++ ) {
|
||||
// char ch = s.charAt(i);
|
||||
@@ -382,26 +396,31 @@ namespace Spring.Http
|
||||
// return isQuotedString(s) ? s.substring(1, s.length() - 1) : s;
|
||||
//}
|
||||
|
||||
/**
|
||||
* Return a generic parameter value, given a parameter name.
|
||||
* @param name the parameter name
|
||||
* @return the parameter value; or <code>null</code> if not present
|
||||
*/
|
||||
/// <summary>
|
||||
/// Return a generic parameter value, given a parameter name.
|
||||
/// </summary>
|
||||
/// <param name="name">The parameter name.</param>
|
||||
/// <returns>The parameter value; or null if not present.</returns>
|
||||
public string GetParameter(string name)
|
||||
{
|
||||
return this.parameters[name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether this {@link MediaType} includes the given media type.
|
||||
* <p>For instance, {@code text/*} includes {@code text/plain}, {@code text/html}, and {@code application/*+xml}
|
||||
* includes {@code application/soap+xml}, etc. This method is non-symmetic.
|
||||
* @param other the reference media type with which to compare
|
||||
* @return <code>true</code> if this media type includes the given media type; <code>false</code> otherwise
|
||||
*/
|
||||
public bool Includes(MediaType other)
|
||||
/// <summary>
|
||||
/// Indicate whether this <see cref="T:MediaType"/> includes the given media type.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For instance, 'text/*' includes 'text/plain', 'text/html', and
|
||||
/// 'application/*+xml' includes 'application/soap+xml', etc.
|
||||
/// This method is non-symmetric.
|
||||
/// </remarks>
|
||||
/// <param name="otherMediaType">The reference media type with which to compare.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if this media type includes the given media type; otherwise <see langword="false"/>.
|
||||
/// </returns>
|
||||
public bool Includes(MediaType otherMediaType)
|
||||
{
|
||||
if (other == null)
|
||||
if (otherMediaType == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -410,21 +429,21 @@ namespace Spring.Http
|
||||
// */* includes anything
|
||||
return true;
|
||||
}
|
||||
else if (this.type == other.type)
|
||||
else if (this.type == otherMediaType.type)
|
||||
{
|
||||
if (this.subtype == other.subtype || this.IsWildcardSubtype)
|
||||
if (this.subtype == otherMediaType.subtype || this.IsWildcardSubtype)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// application/*+xml includes application/soap+xml
|
||||
int thisPlusIdx = this.subtype.IndexOf('+');
|
||||
int otherPlusIdx = other.subtype.IndexOf('+');
|
||||
int otherPlusIdx = otherMediaType.subtype.IndexOf('+');
|
||||
if (thisPlusIdx != -1 && otherPlusIdx != -1)
|
||||
{
|
||||
string thisSubtypeNoSuffix = this.subtype.Substring(0, thisPlusIdx);
|
||||
|
||||
string thisSubtypeSuffix = this.subtype.Substring(thisPlusIdx + 1);
|
||||
string otherSubtypeSuffix = other.subtype.Substring(otherPlusIdx + 1);
|
||||
string otherSubtypeSuffix = otherMediaType.subtype.Substring(otherPlusIdx + 1);
|
||||
if (thisSubtypeSuffix == otherSubtypeSuffix && WILDCARD_TYPE == thisSubtypeNoSuffix)
|
||||
{
|
||||
return true;
|
||||
@@ -434,39 +453,43 @@ namespace Spring.Http
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether this {@link MediaType} is compatible with the given media type.
|
||||
* <p>For instance, {@code text/*} is compatible with {@code text/plain}, {@code text/html}, and vice versa.
|
||||
* In effect, this method is similar to {@link #includes(MediaType)}, except that it's symmetric.
|
||||
* @param other the reference media type with which to compare
|
||||
* @return <code>true</code> if this media type is compatible with the given media type; <code>false</code> otherwise
|
||||
*/
|
||||
public bool IsCompatibleWith(MediaType other)
|
||||
/// <summary>
|
||||
/// Indicate whether this <see cref="T:MediaType"/> is compatible with the given media type.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For instance, 'text/*' is compatible 'text/plain', 'text/html', and vice versa.
|
||||
/// In effect, this method is similar to <see cref="M:Includes(MediaType)"/>, except that it's symmetric.
|
||||
/// </remarks>
|
||||
/// <param name="otherMediaType">The reference media type with which to compare.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if this media type is compatible with the given media type; otherwise <see langword="false"/>.
|
||||
/// </returns>
|
||||
public bool IsCompatibleWith(MediaType otherMediaType)
|
||||
{
|
||||
if (other == null)
|
||||
if (otherMediaType == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this.IsWildcardType || other.IsWildcardType)
|
||||
if (this.IsWildcardType || otherMediaType.IsWildcardType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (this.type == other.type)
|
||||
else if (this.type == otherMediaType.type)
|
||||
{
|
||||
if (this.subtype == other.subtype || this.IsWildcardSubtype || other.IsWildcardSubtype)
|
||||
if (this.subtype == otherMediaType.subtype || this.IsWildcardSubtype || otherMediaType.IsWildcardSubtype)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// application/*+xml is compatible with application/soap+xml, and vice-versa
|
||||
int thisPlusIdx = this.subtype.IndexOf('+');
|
||||
int otherPlusIdx = other.subtype.IndexOf('+');
|
||||
int otherPlusIdx = otherMediaType.subtype.IndexOf('+');
|
||||
if (thisPlusIdx != -1 && otherPlusIdx != -1)
|
||||
{
|
||||
string thisSubtypeNoSuffix = this.subtype.Substring(0, thisPlusIdx);
|
||||
string otherSubtypeNoSuffix = other.subtype.Substring(0, otherPlusIdx);
|
||||
string otherSubtypeNoSuffix = otherMediaType.subtype.Substring(0, otherPlusIdx);
|
||||
|
||||
string thisSubtypeSuffix = this.subtype.Substring(thisPlusIdx + 1);
|
||||
string otherSubtypeSuffix = other.subtype.Substring(otherPlusIdx + 1);
|
||||
string otherSubtypeSuffix = otherMediaType.subtype.Substring(otherPlusIdx + 1);
|
||||
|
||||
if (thisSubtypeSuffix == otherSubtypeSuffix &&
|
||||
(WILDCARD_TYPE == thisSubtypeNoSuffix || WILDCARD_TYPE == otherSubtypeNoSuffix))
|
||||
@@ -480,11 +503,16 @@ namespace Spring.Http
|
||||
|
||||
#region IComparable<MediaType> Membres
|
||||
|
||||
/**
|
||||
* Compares this {@link MediaType} to another alphabetically.
|
||||
* @param other media type to compare to
|
||||
* @see #sortBySpecificity(List)
|
||||
*/
|
||||
/// <summary>
|
||||
/// Compares this <see cref="MediaType"/> to another alphabetically.
|
||||
/// </summary>
|
||||
/// <param name="other">The media type to compare with this object.</param>
|
||||
/// <returns>
|
||||
/// A 32-bit signed integer that indicates the relative order of the objects
|
||||
/// being compared. The return value has the following meanings: Value Meaning
|
||||
/// Less than zero This object is less than the other parameter. Zero This object
|
||||
/// is equal to other. Greater than zero This object is greater than other.
|
||||
/// </returns>
|
||||
public int CompareTo(MediaType other)
|
||||
{
|
||||
int comp = this.type.CompareTo(other.type);
|
||||
@@ -519,15 +547,17 @@ namespace Spring.Http
|
||||
|
||||
#endregion
|
||||
|
||||
/**
|
||||
* Parse the given String into a single {@link MediaType}.
|
||||
* @param mediaType the string to parse
|
||||
* @return the media type
|
||||
* @throws IllegalArgumentException if the string cannot be parsed
|
||||
*/
|
||||
/// <summary>
|
||||
/// Parse the given String into a single <see cref="MediaType"/>.
|
||||
/// </summary>
|
||||
/// <param name="mediaType">The string to parse.</param>
|
||||
/// <returns>The media type.</returns>
|
||||
public static MediaType ParseMediaType(string mediaType)
|
||||
{
|
||||
AssertUtils.ArgumentHasText(mediaType, "'mediaType' must not be empty");
|
||||
if (!StringUtils.HasText(mediaType))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string[] parts = mediaType.Split(';');
|
||||
string fullType = parts[0].Trim();
|
||||
@@ -570,17 +600,18 @@ namespace Spring.Http
|
||||
return new MediaType(type, subtype, parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given, comma-seperated string into a list of {@link MediaType} objects.
|
||||
* <p>This method can be used to parse an Accept or Content-Type header.
|
||||
* @param mediaTypes the string to parse
|
||||
* @return the list of media types
|
||||
* @throws IllegalArgumentException if the string cannot be parsed
|
||||
*/
|
||||
/// <summary>
|
||||
/// Parse the given, comma-seperated string into a list of <see cref="MediaType"/> objects.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method can be used to parse an 'Accept' or 'Content-Type' header.
|
||||
/// </remarks>
|
||||
/// <param name="mediaTypes">The string to parse.</param>
|
||||
/// <returns>The list of media types.</returns>
|
||||
public static List<MediaType> ParseMediaTypes(string mediaTypes)
|
||||
{
|
||||
List<MediaType> mediaTypeList = new List<MediaType>();
|
||||
if (!StringUtils.HasLength(mediaTypes))
|
||||
if (!StringUtils.HasText(mediaTypes))
|
||||
{
|
||||
return mediaTypeList;
|
||||
}
|
||||
@@ -592,13 +623,14 @@ namespace Spring.Http
|
||||
return mediaTypeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string representation of the given list of {@link MediaType} objects.
|
||||
* <p>This method can be used to for an {@code Accept} or {@code Content-Type} header.
|
||||
* @param mediaTypes the string to parse
|
||||
* @return the list of media types
|
||||
* @throws IllegalArgumentException if the String cannot be parsed
|
||||
*/
|
||||
/// <summary>
|
||||
/// Return a string representation of the given list of <see cref="MediaType"/> objects.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method can be used to for an 'Accept' or 'Content-Type' header.
|
||||
/// </remarks>
|
||||
/// <param name="mediaTypes">The list of media types to convert.</param>
|
||||
/// <returns>The string representation of the given list.</returns>
|
||||
public static string ToString(IEnumerable<MediaType> mediaTypes)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
@@ -613,32 +645,38 @@ namespace Spring.Http
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the given list of {@link MediaType} objects by specificity.
|
||||
* <p>Given two media types:
|
||||
* <ol>
|
||||
* <li>if either media type has a {@linkplain #isWildcardType() wildcard type}, then the media type without the
|
||||
* wildcard is ordered before the other.</li>
|
||||
* <li>if the two media types have different {@linkplain #getType() types}, then they are considered equal and
|
||||
* remain their current order.</li>
|
||||
* <li>if either media type has a {@linkplain #isWildcardSubtype() wildcard subtype}, then the media type without
|
||||
* the wildcard is sorted before the other.</li>
|
||||
* <li>if the two media types have different {@linkplain #getSubtype() subtypes}, then they are considered equal
|
||||
* and remain their current order.</li>
|
||||
* <li>if the two media types have different {@linkplain #getQualityValue() quality value}, then the media type
|
||||
* with the highest quality value is ordered before the other.</li>
|
||||
* <li>if the two media types have a different amount of {@linkplain #getParameter(String) parameters}, then the
|
||||
* media type with the most parameters is ordered before the other.</li>
|
||||
* </ol>
|
||||
* <p>For example:
|
||||
* <blockquote>audio/basic < audio/* < */*</blockquote>
|
||||
* <blockquote>audio/* < audio/*;q=0.7; audio/*;q=0.3</blockquote>
|
||||
* <blockquote>audio/basic;level=1 < audio/basic</blockquote>
|
||||
* <blockquote>audio/basic == text/html</blockquote>
|
||||
* <blockquote>audio/basic == audio/wave</blockquote>
|
||||
* @param mediaTypes the list of media types to be sorted
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2616#section-14.1">HTTP 1.1, section 14.1</a>
|
||||
*/
|
||||
/// <summary>
|
||||
/// Sorts the given list of <see cref="MediaType"/> objects by specificity.
|
||||
/// <a href="http://tools.ietf.org/html/rfc2616#section-14.1">HTTP 1.1, section 14.1</a>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Given two media types:
|
||||
/// <ol>
|
||||
/// <li>if either media type has a wildcard type, then the media type without the
|
||||
/// wildcard is ordered before the other.</li>
|
||||
/// <li>if the two media types have different types, then they are considered equal and
|
||||
/// remain their current order.</li>
|
||||
/// <li>if either media type has a wildcard subtype, then the media type without
|
||||
/// the wildcard is sorted before the other.</li>
|
||||
/// <li>if the two media types have different subtypes, then they are considered equal
|
||||
/// and remain their current order.</li>
|
||||
/// <li>if the two media types have different quality value, then the media type
|
||||
/// with the highest quality value is ordered before the other.</li>
|
||||
/// <li>if the two media types have a different amount of parameters, then the
|
||||
/// media type with the most parameters is ordered before the other.</li>
|
||||
/// </ol>
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// For example:
|
||||
/// <blockquote>audio/basic < audio/* < */*</blockquote>
|
||||
/// <blockquote>audio/* < audio/*;q=0.7; audio/*;q=0.3</blockquote>
|
||||
/// <blockquote>audio/basic;level=1 < audio/basic</blockquote>
|
||||
/// <blockquote>audio/basic == text/html</blockquote>
|
||||
/// <blockquote>audio/basic == audio/wave</blockquote>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="mediaTypes">The list of media types to be sorted.</param>
|
||||
public static void SortBySpecificity(List<MediaType> mediaTypes)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(mediaTypes, "mediaTypes");
|
||||
@@ -649,26 +687,29 @@ namespace Spring.Http
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the given list of {@link MediaType} objects by quality value.
|
||||
* <p>Given two media types:
|
||||
* <ol>
|
||||
* <li>if the two media types have different {@linkplain #getQualityValue() quality value}, then the media type
|
||||
* with the highest quality value is ordered before the other.</li>
|
||||
* <li>if either media type has a {@linkplain #isWildcardType() wildcard type}, then the media type without the
|
||||
* wildcard is ordered before the other.</li>
|
||||
* <li>if the two media types have different {@linkplain #getType() types}, then they are considered equal and
|
||||
* remain their current order.</li>
|
||||
* <li>if either media type has a {@linkplain #isWildcardSubtype() wildcard subtype}, then the media type without
|
||||
* the wildcard is sorted before the other.</li>
|
||||
* <li>if the two media types have different {@linkplain #getSubtype() subtypes}, then they are considered equal
|
||||
* and remain their current order.</li>
|
||||
* <li>if the two media types have a different amount of {@linkplain #getParameter(String) parameters}, then the
|
||||
* media type with the most parameters is ordered before the other.</li>
|
||||
* </ol>
|
||||
* @param mediaTypes the list of media types to be sorted
|
||||
* @see #getQualityValue()
|
||||
*/
|
||||
/// <summary>
|
||||
/// Sorts the given list of <see cref="MediaType"/> objects by quality value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Given two media types:
|
||||
/// <ol>
|
||||
/// <li>if the two media types have different quality value, then the media type
|
||||
/// with the highest quality value is ordered before the other.</li>
|
||||
/// <li>if either media type has a wildcard type, then the media type without the
|
||||
/// wildcard is ordered before the other.</li>
|
||||
/// <li>if the two media types have different types, then they are considered equal and
|
||||
/// remain their current order.</li>
|
||||
/// <li>if either media type has a wildcard subtype, then the media type without
|
||||
/// the wildcard is sorted before the other.</li>
|
||||
/// <li>if the two media types have different subtypes, then they are considered equal
|
||||
/// and remain their current order.</li>
|
||||
/// <li>if the two media types have a different amount of parameters, then the
|
||||
/// media type with the most parameters is ordered before the other.</li>
|
||||
/// </ol>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="mediaTypes">The list of media types to be sorted</param>
|
||||
public static void SortByQualityValue(List<MediaType> mediaTypes)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(mediaTypes, "mediaTypes");
|
||||
@@ -679,7 +720,14 @@ namespace Spring.Http
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="IComparer<MediaType>"/> implementation by specificity value.
|
||||
/// </summary>
|
||||
public static IComparer<MediaType> SPECIFICITY_COMPARER = new SpecificityComparer();
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="IComparer<MediaType>"/> implementation by quality value.
|
||||
/// </summary>
|
||||
public static IComparer<MediaType> QUALITY_VALUE_COMPARER = new QualityValueComparer();
|
||||
|
||||
#region SpecificityComparer
|
||||
|
||||
@@ -23,25 +23,31 @@ using System.Net;
|
||||
|
||||
namespace Spring.Http.Rest
|
||||
{
|
||||
/**
|
||||
* Callback interface for code that operates on a {@link ClientHttpRequest}. Allows to manipulate the request
|
||||
* headers, and write to the request body.
|
||||
*
|
||||
* <p>Used internally by the {@link RestTemplate}, but also useful for application code.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see RestTemplate#execute
|
||||
* @since 3.0
|
||||
*/
|
||||
/// <summary>
|
||||
/// Callback interface for code that operates on a <see cref="HttpWebRequest"/>.
|
||||
/// Allows to manipulate the request headers, and write to the request body.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Callback interface used by <see cref="RestTemplate"/>'s senders methods.
|
||||
/// Implementations of this interface perform the actual work of writing data
|
||||
/// to a <see cref="HttpWebRequest"/>, but don't need to worry about exception
|
||||
/// handling or closing resources.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Used internally by the <see cref="RestTemplate"/>, but also useful for application code.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
public interface IRequestCallback
|
||||
{
|
||||
/**
|
||||
* Gets called by {@link RestTemplate#execute} with an opened {@code ClientHttpRequest}.
|
||||
* Does not need to care about closing the request or about handling errors:
|
||||
* this will all be handled by the {@code RestTemplate}.
|
||||
* @param request the active HTTP request
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
/// <summary>
|
||||
/// Gets called by <see cref="RestTemplate"/> with an opened <see cref="HttpWebRequest"/> to write data.
|
||||
/// Does not need to care about closing the request or about handling errors:
|
||||
/// this will all be handled by the <see cref="RestTemplate"/> class.
|
||||
/// </summary>
|
||||
/// <param name="request">The active HTTP request.</param>
|
||||
void DoWithRequest(HttpWebRequest request);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,26 +23,31 @@ using System.Net;
|
||||
|
||||
namespace Spring.Http.Rest
|
||||
{
|
||||
/**
|
||||
* Generic callback interface used by {@link RestTemplate}'s retrieval methods
|
||||
* Implementations of this interface perform the actual work of extracting data
|
||||
* from a {@link ClientHttpResponse}, but don't need to worry about exception
|
||||
* handling or closing resources.
|
||||
*
|
||||
* <p>Used internally by the {@link RestTemplate}, but also useful for application code.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
* @see RestTemplate#execute
|
||||
*/
|
||||
/// <summary>
|
||||
/// Callback interface for code that operates on a <see cref="HttpWebResponse"/>.
|
||||
/// Allows to manipulate the response headers, and extract the response body.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Generic callback interface used by <see cref="RestTemplate"/>'s retrieval methods.
|
||||
/// Implementations of this interface perform the actual work of extracting data
|
||||
/// from a <see cref="HttpWebResponse"/>, but don't need to worry about exception
|
||||
/// handling or closing resources.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Used internally by the <see cref="RestTemplate"/>, but also useful for application code.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
public interface IResponseExtractor<T> where T : class
|
||||
{
|
||||
/**
|
||||
* Extract data from the given {@code ClientHttpResponse} and return it.
|
||||
* @param response the HTTP response
|
||||
* @return the extracted data
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
T ExtractData(HttpWebResponse response); // throws IOException;
|
||||
/// <summary>
|
||||
/// Gets called by <see cref="RestTemplate"/> with an opened <see cref="HttpWebResponse"/> to extract data.
|
||||
/// Does not need to care about closing the request or about handling errors:
|
||||
/// this will all be handled by the <see cref="RestTemplate"/> class.
|
||||
/// </summary>
|
||||
/// <param name="response">The active HTTP request.</param>
|
||||
T ExtractData(HttpWebResponse response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,413 +26,559 @@ using Spring.Http;
|
||||
|
||||
namespace Spring.Http.Rest
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface specifying a basic set of RESTful operations.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Not often used directly, but a useful option to enhance testability, as it can easily be mocked or stubbed.
|
||||
/// </remarks>
|
||||
/// <see cref="RestTemplate"/>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
public interface IRestOperations
|
||||
{
|
||||
#region GET
|
||||
|
||||
/**
|
||||
* Retrieve a representation by doing a GET on the specified URL.
|
||||
* The response (if any) is converted and returned.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* @param url the URL
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the converted object
|
||||
*/
|
||||
T GetForObject<T>(string url, params string[] uriVariables) where T : class; //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Retrieve a representation by doing a GET on the specified URL.
|
||||
/// The response (if any) is converted and returned.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>The converted object</returns>
|
||||
T GetForObject<T>(string url, params string[] uriVariables) where T : class;
|
||||
|
||||
/**
|
||||
* Retrieve a representation by doing a GET on the URI template.
|
||||
* The response (if any) is converted and returned.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
* @param url the URL
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the map containing variables for the URI template
|
||||
* @return the converted object
|
||||
*/
|
||||
T GetForObject<T>(string url, IDictionary<string, string> uriVariables) where T : class; //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Retrieve a representation by doing a GET on the specified URL.
|
||||
/// The response (if any) is converted and returned.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>The converted object</returns>
|
||||
T GetForObject<T>(string url, IDictionary<string, string> uriVariables) where T : class;
|
||||
|
||||
/**
|
||||
* Retrieve a representation by doing a GET on the URL .
|
||||
* The response (if any) is converted and returned.
|
||||
* @param url the URL
|
||||
* @param responseType the type of the return value
|
||||
* @return the converted object
|
||||
*/
|
||||
T GetForObject<T>(Uri url) where T : class; //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Retrieve a representation by doing a GET on the specified URL.
|
||||
/// The response (if any) is converted and returned.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <returns>The converted object</returns>
|
||||
T GetForObject<T>(Uri url) where T : class;
|
||||
|
||||
/**
|
||||
* Retrieve an entity by doing a GET on the specified URL.
|
||||
* The response is converted and stored in an {@link ResponseEntity}.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* @param url the URL
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the entity
|
||||
* @since 3.0.2
|
||||
*/
|
||||
HttpResponseMessage<T> GetForMessage<T>(string url, params string[] uriVariables) where T : class; //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Retrieve an entity by doing a GET on the specified URL.
|
||||
/// The response is converted and stored in an <see cref="HttpResponseMessage{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
HttpResponseMessage<T> GetForMessage<T>(string url, params string[] uriVariables) where T : class;
|
||||
|
||||
/**
|
||||
* Retrieve a representation by doing a GET on the URI template.
|
||||
* The response is converted and stored in an {@link ResponseEntity}.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
* @param url the URL
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the map containing variables for the URI template
|
||||
* @return the converted object
|
||||
* @since 3.0.2
|
||||
*/
|
||||
HttpResponseMessage<T> GetForMessage<T>(string url, IDictionary<string, string> uriVariables) where T : class; //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Retrieve an entity by doing a GET on the specified URL.
|
||||
/// The response is converted and stored in an <see cref="HttpResponseMessage{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
HttpResponseMessage<T> GetForMessage<T>(string url, IDictionary<string, string> uriVariables) where T : class;
|
||||
|
||||
/**
|
||||
* Retrieve a representation by doing a GET on the URL .
|
||||
* The response is converted and stored in an {@link ResponseEntity}.
|
||||
* @param url the URL
|
||||
* @param responseType the type of the return value
|
||||
* @return the converted object
|
||||
* @since 3.0.2
|
||||
*/
|
||||
HttpResponseMessage<T> GetForMessage<T>(Uri url) where T : class; //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Retrieve an entity by doing a GET on the specified URL.
|
||||
/// The response is converted and stored in an <see cref="HttpResponseMessage{T}"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
HttpResponseMessage<T> GetForMessage<T>(Uri url) where T : class;
|
||||
|
||||
#endregion
|
||||
|
||||
#region HEAD
|
||||
|
||||
/**
|
||||
* Retrieve all headers of the resource specified by the URI template.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* @param url the URL
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return all HTTP headers of that resource
|
||||
*/
|
||||
WebHeaderCollection HeadForHeaders(string url, params string[] uriVariables); //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Retrieve all headers of the resource specified by the URI template.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>All HTTP headers of that resource</returns>
|
||||
WebHeaderCollection HeadForHeaders(string url, params string[] uriVariables);
|
||||
|
||||
/**
|
||||
* Retrieve all headers of the resource specified by the URI template.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
* @param url the URL
|
||||
* @param uriVariables the map containing variables for the URI template
|
||||
* @return all HTTP headers of that resource
|
||||
*/
|
||||
WebHeaderCollection HeadForHeaders(string url, IDictionary<string, string> uriVariables); //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Retrieve all headers of the resource specified by the URI template.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>All HTTP headers of that resource</returns>
|
||||
WebHeaderCollection HeadForHeaders(string url, IDictionary<string, string> uriVariables);
|
||||
|
||||
/**
|
||||
* Retrieve all headers of the resource specified by the URL.
|
||||
* @param url the URL
|
||||
* @return all HTTP headers of that resource
|
||||
*/
|
||||
/// <summary>
|
||||
/// Retrieve all headers of the resource specified by the URI template.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <returns>All HTTP headers of that resource</returns>
|
||||
WebHeaderCollection HeadForHeaders(Uri url); //throws RestClientException;
|
||||
|
||||
#endregion
|
||||
|
||||
#region POST
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URI template, and returns the value of the
|
||||
* <code>Location</code> header. This header typically indicates where the new resource is stored.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be <code>null</code>
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the value for the <code>Location</code> header
|
||||
* @see HttpEntity
|
||||
*/
|
||||
Uri PostForLocation(string url, object request, params string[] uriVariables); //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the value of the 'Location' header.
|
||||
/// This header typically indicates where the new resource is stored.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>The value for the Location header.</returns>
|
||||
Uri PostForLocation(string url, object request, params string[] uriVariables);
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URI template, and returns the value of the
|
||||
* <code>Location</code> header. This header typically indicates where the new resource is stored.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be <code>null</code>
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the value for the <code>Location</code> header
|
||||
* @see HttpEntity
|
||||
*/
|
||||
Uri PostForLocation(string url, object request, IDictionary<string, string> uriVariables); //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the value of the 'Location' header.
|
||||
/// This header typically indicates where the new resource is stored.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>The value for the Location header.</returns>
|
||||
Uri PostForLocation(string url, object request, IDictionary<string, string> uriVariables);
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URL, and returns the value of the
|
||||
* <code>Location</code> header. This header typically indicates where the new resource is stored.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be <code>null</code>
|
||||
* @return the value for the <code>Location</code> header
|
||||
* @see HttpEntity
|
||||
*/
|
||||
Uri PostForLocation(Uri url, object request); //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the value of the 'Location' header.
|
||||
/// This header typically indicates where the new resource is stored.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <returns>The value for the Location header.</returns>
|
||||
Uri PostForLocation(Uri url, object request);
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URI template,
|
||||
* and returns the representation found in the response.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be <code>null</code>
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the converted object
|
||||
* @see HttpEntity
|
||||
*/
|
||||
T PostForObject<T>(string url, object request, params string[] uriVariables) where T : class; //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the representation found in the response.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>The converted object.</returns>
|
||||
T PostForObject<T>(string url, object request, params string[] uriVariables) where T : class;
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URI template,
|
||||
* and returns the representation found in the response.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be <code>null</code>
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the converted object
|
||||
* @see HttpEntity
|
||||
*/
|
||||
T PostForObject<T>(string url, object request, IDictionary<string, string> uriVariables) where T : class; //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the representation found in the response.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>The converted object.</returns>
|
||||
T PostForObject<T>(string url, object request, IDictionary<string, string> uriVariables) where T : class;
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URL,
|
||||
* and returns the representation found in the response.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be <code>null</code>
|
||||
* @param responseType the type of the return value
|
||||
* @return the converted object
|
||||
* @see HttpEntity
|
||||
*/
|
||||
T PostForObject<T>(Uri url, object request) where T : class; //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the representation found in the response.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <returns>The converted object.</returns>
|
||||
T PostForObject<T>(Uri url, object request) where T : class;
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URI template,
|
||||
* and returns the response as {@link ResponseEntity}.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be <code>null</code>
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the converted object
|
||||
* @see HttpEntity
|
||||
* @since 3.0.2
|
||||
*/
|
||||
HttpResponseMessage<T> PostForMessage<T>(string url, object request, params string[] uriVariables) where T : class; //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the response as <see cref="HttpResponseMessage{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
HttpResponseMessage<T> PostForMessage<T>(string url, object request, params string[] uriVariables) where T : class;
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URI template,
|
||||
* and returns the response as {@link HttpEntity}.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be <code>null</code>
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the converted object
|
||||
* @see HttpEntity
|
||||
* @since 3.0.2
|
||||
*/
|
||||
HttpResponseMessage<T> PostForMessage<T>(string url, object request, IDictionary<string, string> uriVariables) where T : class; //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the response as <see cref="HttpResponseMessage{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
HttpResponseMessage<T> PostForMessage<T>(string url, object request, IDictionary<string, string> uriVariables) where T : class;
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URL,
|
||||
* and returns the response as {@link ResponseEntity}.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be <code>null</code>
|
||||
* @return the converted object
|
||||
* @see HttpEntity
|
||||
* @since 3.0.2
|
||||
*/
|
||||
HttpResponseMessage<T> PostForMessage<T>(Uri url, object request) where T : class; //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the response as <see cref="HttpResponseMessage{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
HttpResponseMessage<T> PostForMessage<T>(Uri url, object request) where T : class;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the response with no entity as <see cref="HttpResponseMessage"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>The HTTP response message with no entity.</returns>
|
||||
HttpResponseMessage PostForMessage(string url, object request, params string[] uriVariables);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the response with no entity as <see cref="HttpResponseMessage"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>The HTTP response message with no entity.</returns>
|
||||
HttpResponseMessage PostForMessage(string url, object request, IDictionary<string, string> uriVariables);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the response with no entity as <see cref="HttpResponseMessage"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <returns>The HTTP response message with no entity.</returns>
|
||||
HttpResponseMessage PostForMessage(Uri url, object request);
|
||||
|
||||
#endregion
|
||||
|
||||
#region PUT
|
||||
|
||||
/**
|
||||
* Create or update a resource by PUTting the given object to the URI.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be PUT, may be <code>null</code>
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @see HttpEntity
|
||||
*/
|
||||
void Put(string url, object request, params string[] uriVariables); //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Create or update a resource by PUTting the given object to the URI.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be PUT, may be null.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
void Put(string url, object request, params string[] uriVariables);
|
||||
|
||||
/**
|
||||
* Creates a new resource by PUTting the given object to URI template.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be PUT, may be <code>null</code>
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @see HttpEntity
|
||||
*/
|
||||
void Put(string url, object request, IDictionary<string, string> uriVariables); //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Create or update a resource by PUTting the given object to the URI.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be PUT, may be null.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
void Put(string url, object request, IDictionary<string, string> uriVariables);
|
||||
|
||||
/**
|
||||
* Creates a new resource by PUTting the given object to URL.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be PUT, may be <code>null</code>
|
||||
* @see HttpEntity
|
||||
*/
|
||||
void Put(Uri url, object request); //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Create or update a resource by PUTting the given object to the URI.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be PUT, may be null.</param>
|
||||
void Put(Uri url, object request);
|
||||
|
||||
#endregion
|
||||
|
||||
#region DELETE
|
||||
|
||||
/**
|
||||
* Delete the resources at the specified URI.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* @param url the URL
|
||||
* @param uriVariables the variables to expand in the template
|
||||
*/
|
||||
void Delete(string url, params string[] uriVariables); //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Delete the resources at the specified URI.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
void Delete(string url, params string[] uriVariables);
|
||||
|
||||
/**
|
||||
* Delete the resources at the specified URI.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
*
|
||||
* @param url the URL
|
||||
* @param uriVariables the variables to expand the template
|
||||
*/
|
||||
void Delete(string url, IDictionary<string, string> uriVariables); //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Delete the resources at the specified URI.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
void Delete(string url, IDictionary<string, string> uriVariables);
|
||||
|
||||
/**
|
||||
* Delete the resources at the specified URL.
|
||||
* @param url the URL
|
||||
*/
|
||||
void Delete(Uri url); //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Delete the resources at the specified URI.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL.</param>
|
||||
void Delete(Uri url);
|
||||
|
||||
#endregion
|
||||
|
||||
#region OPTIONS
|
||||
|
||||
/**
|
||||
* Return the value of the Allow header for the given URI.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* @param url the URL
|
||||
* @param uriVariables the variables to expand in the template
|
||||
* @return the value of the allow header
|
||||
*/
|
||||
IList<HttpMethod> OptionsForAllow(string url, params string[] uriVariables); //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Return the value of the Allow header for the given URI.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>The value of the allow header.</returns>
|
||||
IList<HttpMethod> OptionsForAllow(string url, params string[] uriVariables);
|
||||
|
||||
/**
|
||||
* Return the value of the Allow header for the given URI.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
* @param url the URL
|
||||
* @param uriVariables the variables to expand in the template
|
||||
* @return the value of the allow header
|
||||
*/
|
||||
IList<HttpMethod> OptionsForAllow(string url, IDictionary<string, string> uriVariables); //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Return the value of the Allow header for the given URI.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>The value of the allow header.</returns>
|
||||
IList<HttpMethod> OptionsForAllow(string url, IDictionary<string, string> uriVariables);
|
||||
|
||||
/**
|
||||
* Return the value of the Allow header for the given URL.
|
||||
* @param url the URL
|
||||
* @return the value of the allow header
|
||||
*/
|
||||
IList<HttpMethod> OptionsForAllow(Uri url); //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Return the value of the Allow header for the given URI.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <returns>The value of the allow header.</returns>
|
||||
IList<HttpMethod> OptionsForAllow(Uri url);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Exchange
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given URI template, writing the given request entity to the request, and
|
||||
* returns the response as {@link ResponseEntity}.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* @param url the URL
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand in the template
|
||||
* @return the response as entity
|
||||
* @since 3.0.2
|
||||
*/
|
||||
HttpResponseMessage<T> Exchange<T>(string url, HttpRequestMessage requestMessage, params string[] uriVariables) where T : class; //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Execute the HTTP request to the given URI template, writing the given request message to the request,
|
||||
/// and returns the response as <see cref="HttpResponseMessage{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="requestMessage">The HTTP request message to write to the request.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
HttpResponseMessage<T> Exchange<T>(string url, HttpRequestMessage requestMessage, params string[] uriVariables) where T : class;
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given URI template, writing the given request entity to the request, and
|
||||
* returns the response as {@link ResponseEntity}.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* @param url the URL
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand in the template
|
||||
* @return the response as entity
|
||||
* @since 3.0.2
|
||||
*/
|
||||
HttpResponseMessage<T> Exchange<T>(string url, HttpRequestMessage requestMessage, IDictionary<string, string> uriVariables) where T : class; //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Execute the HTTP request to the given URI template, writing the given request message to the request,
|
||||
/// and returns the response as <see cref="HttpResponseMessage{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="requestMessage">The HTTP request message to write to the request.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
HttpResponseMessage<T> Exchange<T>(string url, HttpRequestMessage requestMessage, IDictionary<string, string> uriVariables) where T : class;
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given URI template, writing the given request entity to the request, and
|
||||
* returns the response as {@link ResponseEntity}.
|
||||
* @param url the URL
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}
|
||||
* @param responseType the type of the return value
|
||||
* @return the response as entity
|
||||
* @since 3.0.2
|
||||
*/
|
||||
HttpResponseMessage<T> Exchange<T>(Uri url, HttpRequestMessage requestMessage) where T : class; //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Execute the HTTP request to the given URI template, writing the given request message to the request,
|
||||
/// and returns the response as <see cref="HttpResponseMessage{T}"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="requestMessage">The HTTP request message to write to the request.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
HttpResponseMessage<T> Exchange<T>(Uri url, HttpRequestMessage requestMessage) where T : class;
|
||||
|
||||
/// <summary>
|
||||
/// Execute the HTTP request to the given URI template, writing the given request message to the request,
|
||||
/// and returns the response with no entity as <see cref="HttpResponseMessage"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="requestMessage">The HTTP request message to write to the request.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>The HTTP response message with no entity.</returns>
|
||||
HttpResponseMessage Exchange(string url, HttpRequestMessage requestMessage, params string[] uriVariables);
|
||||
|
||||
/// <summary>
|
||||
/// Execute the HTTP request to the given URI template, writing the given request message to the request,
|
||||
/// and returns the response with no entity as <see cref="HttpResponseMessage"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="requestMessage">The HTTP request message to write to the request.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>The HTTP response message with no entity.</returns>
|
||||
HttpResponseMessage Exchange(string url, HttpRequestMessage requestMessage, IDictionary<string, string> uriVariables);
|
||||
|
||||
/// <summary>
|
||||
/// Execute the HTTP request to the given URI template, writing the given request message to the request,
|
||||
/// and returns the response with no entity as <see cref="HttpResponseMessage"/>.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="requestMessage">The HTTP request message to write to the request.</param>
|
||||
/// <returns>The HTTP response message with no entity.</returns>
|
||||
HttpResponseMessage Exchange(Uri url, HttpRequestMessage requestMessage);
|
||||
|
||||
#endregion
|
||||
|
||||
#region General execution
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given URI template, preparing the request with the
|
||||
* {@link RequestCallback}, and reading the response with a {@link ResponseExtractor}.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* @param url the URL
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param requestCallback object that prepares the request
|
||||
* @param responseExtractor object that extracts the return value from the response
|
||||
* @param uriVariables the variables to expand in the template
|
||||
* @return an arbitrary object, as returned by the {@link ResponseExtractor}
|
||||
*/
|
||||
/// <summary>
|
||||
/// Execute the HTTP request to the given URI template, preparing the request with the
|
||||
/// <see cref="IRequestCallback"/>, and reading the response with an <see cref="IResponseExtractor{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="requestCallback">Object that prepares the request.</param>
|
||||
/// <param name="responseExtractor">Object that extracts the return value from the response.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>An arbitrary object, as returned by the <see cref="IResponseExtractor{T}"/>.</returns>
|
||||
T Execute<T>(string url, IRequestCallback requestCallback, IResponseExtractor<T> responseExtractor, params string[] uriVariables) where T : class; //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given URI template, preparing the request with the
|
||||
* {@link RequestCallback}, and reading the response with a {@link ResponseExtractor}.
|
||||
* <p>URI Template variables are expanded using the given URI variables map.
|
||||
* @param url the URL
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param requestCallback object that prepares the request
|
||||
* @param responseExtractor object that extracts the return value from the response
|
||||
* @param uriVariables the variables to expand in the template
|
||||
* @return an arbitrary object, as returned by the {@link ResponseExtractor}
|
||||
*/
|
||||
T Execute<T>(string url, IRequestCallback requestCallback, IResponseExtractor<T> responseExtractor, IDictionary<string, string> uriVariables) where T : class; //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Execute the HTTP request to the given URI template, preparing the request with the
|
||||
/// <see cref="IRequestCallback"/>, and reading the response with an <see cref="IResponseExtractor{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="requestCallback">Object that prepares the request.</param>
|
||||
/// <param name="responseExtractor">Object that extracts the return value from the response.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>An arbitrary object, as returned by the <see cref="IResponseExtractor{T}"/>.</returns>
|
||||
T Execute<T>(string url, IRequestCallback requestCallback, IResponseExtractor<T> responseExtractor, IDictionary<string, string> uriVariables) where T : class;
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given URL, preparing the request with the
|
||||
* {@link RequestCallback}, and reading the response with a {@link ResponseExtractor}.
|
||||
* @param url the URL
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param requestCallback object that prepares the request
|
||||
* @param responseExtractor object that extracts the return value from the response
|
||||
* @return an arbitrary object, as returned by the {@link ResponseExtractor}
|
||||
*/
|
||||
T Execute<T>(Uri url, IRequestCallback requestCallback, IResponseExtractor<T> responseExtractor) where T : class; //throws RestClientException;
|
||||
/// <summary>
|
||||
/// Execute the HTTP request to the given URI template, preparing the request with the
|
||||
/// <see cref="IRequestCallback"/>, and reading the response with an <see cref="IResponseExtractor{T}"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="requestCallback">Object that prepares the request.</param>
|
||||
/// <param name="responseExtractor">Object that extracts the return value from the response.</param>
|
||||
/// <returns>An arbitrary object, as returned by the <see cref="IResponseExtractor{T}"/>.</returns>
|
||||
T Execute<T>(Uri url, IRequestCallback requestCallback, IResponseExtractor<T> responseExtractor) where T : class;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -23,19 +23,23 @@ using System.Runtime.Serialization;
|
||||
|
||||
namespace Spring.Http.Rest
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for exceptions thrown by <see cref="RestTemplate"/> whenever it encounters client-side HTTP errors.
|
||||
/// </summary>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
[Serializable]
|
||||
public class RestClientException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the
|
||||
/// RestClientException class.
|
||||
/// Creates a new instance of the <see cref="RestClientException"/> class.
|
||||
/// </summary>
|
||||
public RestClientException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the RestClientException class.
|
||||
/// Creates a new instance of the <see cref="RestClientException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">
|
||||
/// A message about the exception.
|
||||
@@ -46,7 +50,7 @@ namespace Spring.Http.Rest
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the RestClientException class.
|
||||
/// Creates a new instance of the <see cref="RestClientException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">
|
||||
/// A message about the exception.
|
||||
@@ -60,7 +64,7 @@ namespace Spring.Http.Rest
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the RestClientException class.
|
||||
/// Creates a new instance of the <see cref="RestClientException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="info">
|
||||
/// The <see cref="System.Runtime.Serialization.SerializationInfo"/>
|
||||
|
||||
@@ -23,7 +23,6 @@ using System.IO;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Spring.Util;
|
||||
using Spring.Http;
|
||||
using Spring.Http.Converters;
|
||||
using Spring.Http.Converters.Xml;
|
||||
@@ -31,73 +30,73 @@ using Spring.Http.Converters.Json;
|
||||
using Spring.Http.Converters.Feed;
|
||||
using Spring.Http.Rest.Support;
|
||||
using UriTemplate = Spring.Util.UriTemplate; // UriTemplate in .NET Framework since 3.5
|
||||
using AssertUtils = Spring.Util.AssertUtils;
|
||||
using StringUtils = Spring.Util.StringUtils;
|
||||
|
||||
namespace Spring.Http.Rest
|
||||
{
|
||||
/**
|
||||
* <strong>The central class for client-side HTTP access.</strong> It simplifies communication with HTTP servers, and
|
||||
* enforces RESTful principles. It handles HTTP connections, leaving application code to provide URLs (with possible
|
||||
* template variables) and extract results.
|
||||
*
|
||||
* <p>The main entry points of this template are the methods named after the six main HTTP methods:
|
||||
* <table>
|
||||
* <tr><th>HTTP method</th><th>RestTemplate methods</th></tr>
|
||||
* <tr><td>DELETE</td><td>{@link #delete}</td></tr>
|
||||
* <tr><td>GET</td><td>{@link #getForObject}</td></tr>
|
||||
* <tr><td></td><td>{@link #getForEntity}</td></tr>
|
||||
* <tr><td>HEAD</td><td>{@link #headForHeaders}</td></tr>
|
||||
* <tr><td>OPTIONS</td><td>{@link #optionsForAllow}</td></tr>
|
||||
* <tr><td>POST</td><td>{@link #postForLocation}</td></tr>
|
||||
* <tr><td></td><td>{@link #postForObject}</td></tr>
|
||||
* <tr><td>PUT</td><td>{@link #put}</td></tr>
|
||||
* <tr><td>any</td><td>{@link #exchange}</td></tr>
|
||||
* <tr><td></td><td>{@link #execute}</td></tr> </table>
|
||||
*
|
||||
* <p>For each of these HTTP methods, there are three corresponding Java methods in the {@code RestTemplate}. Two
|
||||
* variant take a {@code String} URI as first argument (eg. {@link #getForObject(String, Class, Object[])}, {@link
|
||||
* #getForObject(String, Class, Map)}), and are capable of substituting any {@linkplain UriTemplate URI templates} in
|
||||
* that URL using either a {@code String} variable arguments array, or a {@code Map<String, String>}. The string varargs
|
||||
* variant expands the given template variables in order, so that
|
||||
* <pre>
|
||||
* String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}", String.class,"42",
|
||||
* "21");
|
||||
* </pre>
|
||||
* will perform a GET on {@code http://example.com/hotels/42/bookings/21}. The map variant expands the template based on
|
||||
* variable name, and is therefore more useful when using many variables, or when a single variable is used multiple
|
||||
* times. For example:
|
||||
* <pre>
|
||||
* Map<String, String> vars = Collections.singletonMap("hotel", "42");
|
||||
* String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);
|
||||
* </pre>
|
||||
* will perform a GET on {@code http://example.com/hotels/42/rooms/42}. Alternatively, there are {@link URI} variant
|
||||
* methods ({@link #getForObject(URI, Class)}), which do not allow for URI templates, but allow you to reuse a single,
|
||||
* expanded URI multiple times.
|
||||
*
|
||||
* <p>Furthermore, the {@code String}-argument methods assume that the URL String is unencoded. This means that
|
||||
* <pre>
|
||||
* restTemplate.getForObject("http://example.com/hotel list");
|
||||
* </pre>
|
||||
* will perform a GET on {@code http://example.com/hotel%20list}. As a result, any URL passed that is already encoded
|
||||
* will be encoded twice (i.e. {@code http://example.com/hotel%20list} will become {@code
|
||||
* http://example.com/hotel%2520list}). If this behavior is undesirable, use the {@code URI}-argument methods, which
|
||||
* will not perform any URL encoding.
|
||||
*
|
||||
* <p>Objects passed to and returned from these methods are converted to and from HTTP messages by {@link
|
||||
* HttpMessageConverter} instances. Converters for the main mime types are registered by default, but you can also write
|
||||
* your own converter and register it via the {@link #setMessageConverters messageConverters} bean property.
|
||||
*
|
||||
* <p>This template uses a {@link org.springframework.http.client.SimpleClientHttpRequestFactory} and a {@link
|
||||
* DefaultResponseErrorHandler} as default strategies for creating HTTP connections or handling HTTP errors,
|
||||
* respectively. These defaults can be overridden through the {@link #setRequestFactory(ClientHttpRequestFactory)
|
||||
* requestFactory} and {@link #setErrorHandler(ResponseErrorHandler) errorHandler} bean properties.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see HttpMessageConverter
|
||||
* @see RequestCallback
|
||||
* @see ResponseExtractor
|
||||
* @see ResponseErrorHandler
|
||||
* @since 3.0
|
||||
*/
|
||||
/// <summary>
|
||||
/// The central class for client-side HTTP access.
|
||||
/// It simplifies communication with HTTP servers, and enforces RESTful principles.
|
||||
/// It handles HTTP connections, leaving application code to provide URLs (with possible template variables) and extract results.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The main entry points of this template are the methods named after the six main HTTP methods:
|
||||
/// <table>
|
||||
/// <tr><th>HTTP method</th><th>RestTemplate methods</th></tr>
|
||||
/// <tr><td>DELETE</td><td><see cref="M:Delete"/></td></tr>
|
||||
/// <tr><td>GET</td><td><see cref="M:GetForObject"/></td></tr>
|
||||
/// <tr><td></td><td><see cref="M:GetForMessage"/></td></tr>
|
||||
/// <tr><td>HEAD</td><td><see cref="M:HeadForHeaders"/></td></tr>
|
||||
/// <tr><td>OPTIONS</td><td><see cref="M:OptionsForAllow"/></td></tr>
|
||||
/// <tr><td>POST</td><td><see cref="M:PostForLocation"/></td></tr>
|
||||
/// <tr><td></td><td><see cref="M:PostForObject"/></td></tr>
|
||||
/// <tr><td>PUT</td><td><see cref="M:Put"/></td></tr>
|
||||
/// <tr><td>any</td><td><see cref="M:Exchange"/></td></tr>
|
||||
/// <tr><td></td><td><see cref="M:Execute"/></td></tr>
|
||||
/// </table>
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// For each of these HTTP methods, there are three corresponding Java methods in the <see cref="RestTemplate"/>.
|
||||
/// Two variant take a string URI as first argument and are capable of substituting any URI templates in
|
||||
/// that URL using either a string variable arguments array, or a string dictionary.
|
||||
/// The string varargs variant expands the given template variables in order, so that
|
||||
/// <code>
|
||||
/// string result = restTemplate.GetForObject<string>("http://example.com/hotels/{hotel}/bookings/{booking}", "42", "21");
|
||||
/// </code>
|
||||
/// will perform a GET on 'http://example.com/hotels/42/bookings/21'. The map variant expands the template based on
|
||||
/// variable name, and is therefore more useful when using many variables, or when a single variable is used multiple
|
||||
/// times. For example:
|
||||
/// <code>
|
||||
/// IDictionary<String, String> vars = new Dictionary<String, String>();
|
||||
/// vars.Add("hotel", "42");
|
||||
/// string result = restTemplate.GetForObject<string>("http://example.com/hotels/{hotel}/rooms/{hotel}", vars);
|
||||
/// </code>
|
||||
/// will perform a GET on 'http://example.com/hotels/42/rooms/42'. Alternatively, there are URI variant
|
||||
/// methods, which do not allow for URI templates, but allow you to reuse a single, expanded URI multiple times.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Furthermore, the string-argument methods assume that the URL String is unencoded. This means that
|
||||
/// <code>
|
||||
/// restTemplate.GetForObject<string>("http://example.com/hotel list");
|
||||
/// </code>
|
||||
/// will perform a GET on 'http://example.com/hotel%20list'.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Objects passed to and returned from these methods are converted to and from HTTP messages by
|
||||
/// <see cref="IHttpMessageConverter"/> instances. Converters for the main mime types are registered by default,
|
||||
/// but you can also write your own converter and register it via the <see cref="P:MessageConverters"/> property.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This template uses a <see cref="T:DefaultHttpWebRequestFactory"/> as default strategy for creating HTTP connections.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <see cref="IHttpMessageConverter"/>
|
||||
/// <see cref="IRequestCallback"/>
|
||||
/// <see cref="IResponseExtractor{T}"/>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
public class RestTemplate : IRestOperations
|
||||
{
|
||||
#region Logging
|
||||
@@ -116,6 +115,9 @@ namespace Spring.Http.Rest
|
||||
private IResponseExtractor<WebHeaderCollection> headersExtractor;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the base URL for the request.
|
||||
/// </summary>
|
||||
public Uri BaseAddress
|
||||
{
|
||||
get
|
||||
@@ -133,18 +135,29 @@ namespace Spring.Http.Rest
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if an exception is thrown when a HTTP client or server error happens (HTTP status code 3xx or 4xx).
|
||||
/// By default, the value is <see langword="true"/> to be consistent with .NET behavior in <see cref="M:HttpWebRequest.GetResponse()"/>.
|
||||
/// </summary>
|
||||
public bool ThrowExceptionOnError
|
||||
{
|
||||
get { return _throwExceptionOnError; }
|
||||
set { _throwExceptionOnError = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the message converters.
|
||||
/// These converters are used to convert from and to HTTP request and response messages.
|
||||
/// </summary>
|
||||
public IList<IHttpMessageConverter> MessageConverters
|
||||
{
|
||||
get { return this._messageConverters; }
|
||||
set { this._messageConverters = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the request factory that this class uses for obtaining for <see cref="HttpWebRequest"/> objects.
|
||||
/// </summary>
|
||||
public IHttpWebRequestFactory RequestFactory
|
||||
{
|
||||
get { return this._requestFactory; }
|
||||
@@ -155,19 +168,29 @@ namespace Spring.Http.Rest
|
||||
|
||||
#region Constructor(s)
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="RestTemplate"/>.
|
||||
/// </summary>
|
||||
/// <param name="baseAddress">The base address to use.</param>
|
||||
public RestTemplate(Uri baseAddress) :
|
||||
this()
|
||||
{
|
||||
this.BaseAddress = baseAddress;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="RestTemplate"/>.
|
||||
/// </summary>
|
||||
/// <param name="baseAddress">The base address to use.</param>
|
||||
public RestTemplate(string baseAddress) :
|
||||
this()
|
||||
{
|
||||
this.BaseAddress = new Uri(baseAddress, UriKind.Absolute);
|
||||
}
|
||||
|
||||
/** Create a new instance of the {@link RestTemplate} using default settings. */
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="RestTemplate"/>.
|
||||
/// </summary>
|
||||
public RestTemplate()
|
||||
{
|
||||
this._throwExceptionOnError = true;
|
||||
@@ -175,22 +198,35 @@ namespace Spring.Http.Rest
|
||||
this._requestFactory = new DefaultHttpWebRequestFactory();
|
||||
|
||||
this._messageConverters = new List<IHttpMessageConverter>();
|
||||
#if NET_3_5
|
||||
//this._messageConverters.Add(new JsonHttpMessageConverter());
|
||||
this._messageConverters.Add(new Atom10FeedHttpMessageConverter());
|
||||
this._messageConverters.Add(new Rss20FeedHttpMessageConverter());
|
||||
this._messageConverters.Add(new XElementHttpMessageConverter());
|
||||
#endif
|
||||
this._messageConverters.Add(new XmlDocumentHttpMessageConverter());
|
||||
//this._messageConverters.Add(new XmlSerializableHttpMessageConverter());
|
||||
this._messageConverters.Add(new StringHttpMessageConverter());
|
||||
|
||||
this._messageConverters.Add(new ByteArrayHttpMessageConverter());
|
||||
this._messageConverters.Add(new StringHttpMessageConverter());
|
||||
//this._messageConverters.Add(new XmlSerializableHttpMessageConverter());
|
||||
this._messageConverters.Add(new XmlDocumentHttpMessageConverter());
|
||||
#if NET_3_5
|
||||
this._messageConverters.Add(new DataContractHttpMessageConverter());
|
||||
this._messageConverters.Add(new XElementHttpMessageConverter());
|
||||
this._messageConverters.Add(new Rss20FeedHttpMessageConverter());
|
||||
this._messageConverters.Add(new Atom10FeedHttpMessageConverter());
|
||||
//this._messageConverters.Add(new JsonHttpMessageConverter());
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IRestOperations Membres
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a representation by doing a GET on the specified URL.
|
||||
/// The response (if any) is converted and returned.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>The converted object</returns>
|
||||
public T GetForObject<T>(string url, params string[] uriVariables) where T : class
|
||||
{
|
||||
AcceptHeaderRequestCallback requestCallback = new AcceptHeaderRequestCallback(HttpMethod.GET, typeof(T), this._messageConverters);
|
||||
@@ -198,6 +234,17 @@ namespace Spring.Http.Rest
|
||||
return this.Execute<T>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a representation by doing a GET on the specified URL.
|
||||
/// The response (if any) is converted and returned.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>The converted object</returns>
|
||||
public T GetForObject<T>(string url, IDictionary<string, string> uriVariables) where T : class
|
||||
{
|
||||
AcceptHeaderRequestCallback requestCallback = new AcceptHeaderRequestCallback(HttpMethod.GET, typeof(T), this._messageConverters);
|
||||
@@ -205,6 +252,13 @@ namespace Spring.Http.Rest
|
||||
return this.Execute<T>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a representation by doing a GET on the specified URL.
|
||||
/// The response (if any) is converted and returned.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <returns>The converted object</returns>
|
||||
public T GetForObject<T>(Uri url) where T : class
|
||||
{
|
||||
AcceptHeaderRequestCallback requestCallback = new AcceptHeaderRequestCallback(HttpMethod.GET, typeof(T), this._messageConverters);
|
||||
@@ -212,6 +266,17 @@ namespace Spring.Http.Rest
|
||||
return this.Execute<T>(url, requestCallback, responseExtractor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve an entity by doing a GET on the specified URL.
|
||||
/// The response is converted and stored in an <see cref="HttpResponseMessage{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
public HttpResponseMessage<T> GetForMessage<T>(string url, params string[] uriVariables) where T : class
|
||||
{
|
||||
AcceptHeaderRequestCallback requestCallback = new AcceptHeaderRequestCallback(HttpMethod.GET, typeof(T), this._messageConverters);
|
||||
@@ -219,6 +284,17 @@ namespace Spring.Http.Rest
|
||||
return this.Execute<HttpResponseMessage<T>>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve an entity by doing a GET on the specified URL.
|
||||
/// The response is converted and stored in an <see cref="HttpResponseMessage{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
public HttpResponseMessage<T> GetForMessage<T>(string url, IDictionary<string, string> uriVariables) where T : class
|
||||
{
|
||||
AcceptHeaderRequestCallback requestCallback = new AcceptHeaderRequestCallback(HttpMethod.GET, typeof(T), this._messageConverters);
|
||||
@@ -226,6 +302,13 @@ namespace Spring.Http.Rest
|
||||
return this.Execute<HttpResponseMessage<T>>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve an entity by doing a GET on the specified URL.
|
||||
/// The response is converted and stored in an <see cref="HttpResponseMessage{T}"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
public HttpResponseMessage<T> GetForMessage<T>(Uri url) where T : class
|
||||
{
|
||||
AcceptHeaderRequestCallback requestCallback = new AcceptHeaderRequestCallback(HttpMethod.GET, typeof(T), this._messageConverters);
|
||||
@@ -233,24 +316,64 @@ namespace Spring.Http.Rest
|
||||
return this.Execute<HttpResponseMessage<T>>(url, requestCallback, responseExtractor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve all headers of the resource specified by the URI template.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>All HTTP headers of that resource</returns>
|
||||
public WebHeaderCollection HeadForHeaders(string url, params string[] uriVariables)
|
||||
{
|
||||
MethodRequestCallback requestCallback = new MethodRequestCallback(HttpMethod.HEAD);
|
||||
return this.Execute<WebHeaderCollection>(url, requestCallback, this.headersExtractor, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve all headers of the resource specified by the URI template.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>All HTTP headers of that resource</returns>
|
||||
public WebHeaderCollection HeadForHeaders(string url, IDictionary<string, string> uriVariables)
|
||||
{
|
||||
MethodRequestCallback requestCallback = new MethodRequestCallback(HttpMethod.HEAD);
|
||||
return this.Execute<WebHeaderCollection>(url, requestCallback, this.headersExtractor, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve all headers of the resource specified by the URI template.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <returns>All HTTP headers of that resource</returns>
|
||||
public WebHeaderCollection HeadForHeaders(Uri url)
|
||||
{
|
||||
MethodRequestCallback requestCallback = new MethodRequestCallback(HttpMethod.HEAD);
|
||||
return this.Execute<WebHeaderCollection>(url, requestCallback, this.headersExtractor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the value of the 'Location' header.
|
||||
/// This header typically indicates where the new resource is stored.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>The value for the Location header.</returns>
|
||||
public Uri PostForLocation(string url, object request, params string[] uriVariables)
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
@@ -261,6 +384,23 @@ namespace Spring.Http.Rest
|
||||
return StringUtils.HasText(location) ? new Uri(location) : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the value of the 'Location' header.
|
||||
/// This header typically indicates where the new resource is stored.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>The value for the Location header.</returns>
|
||||
public Uri PostForLocation(string url, object request, IDictionary<string, string> uriVariables)
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
@@ -271,6 +411,17 @@ namespace Spring.Http.Rest
|
||||
return StringUtils.HasText(location) ? new Uri(location) : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the value of the 'Location' header.
|
||||
/// This header typically indicates where the new resource is stored.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <returns>The value for the Location header.</returns>
|
||||
public Uri PostForLocation(Uri url, object request)
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
@@ -281,6 +432,23 @@ namespace Spring.Http.Rest
|
||||
return StringUtils.HasText(location) ? new Uri(location) : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the representation found in the response.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>The converted object.</returns>
|
||||
public T PostForObject<T>(string url, object request, params string[] uriVariables) where T : class
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
@@ -289,6 +457,23 @@ namespace Spring.Http.Rest
|
||||
return this.Execute<T>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the representation found in the response.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>The converted object.</returns>
|
||||
public T PostForObject<T>(string url, object request, IDictionary<string, string> uriVariables) where T : class
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
@@ -297,6 +482,17 @@ namespace Spring.Http.Rest
|
||||
return this.Execute<T>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the representation found in the response.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <returns>The converted object.</returns>
|
||||
public T PostForObject<T>(Uri url, object request) where T : class
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
@@ -305,6 +501,23 @@ namespace Spring.Http.Rest
|
||||
return this.Execute<T>(url, requestCallback, responseExtractor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the response as <see cref="HttpResponseMessage{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
public HttpResponseMessage<T> PostForMessage<T>(string url, object request, params string[] uriVariables) where T : class
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
@@ -313,6 +526,23 @@ namespace Spring.Http.Rest
|
||||
return this.Execute<HttpResponseMessage<T>>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the response as <see cref="HttpResponseMessage{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
public HttpResponseMessage<T> PostForMessage<T>(string url, object request, IDictionary<string, string> uriVariables) where T : class
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
@@ -321,6 +551,17 @@ namespace Spring.Http.Rest
|
||||
return this.Execute<HttpResponseMessage<T>>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the response as <see cref="HttpResponseMessage{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
public HttpResponseMessage<T> PostForMessage<T>(Uri url, object request) where T : class
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
@@ -329,6 +570,86 @@ namespace Spring.Http.Rest
|
||||
return this.Execute<HttpResponseMessage<T>>(url, requestCallback, responseExtractor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the response with no entity as <see cref="HttpResponseMessage"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>The HTTP response message with no entity.</returns>
|
||||
public HttpResponseMessage PostForMessage(string url, object request, params string[] uriVariables)
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
HttpMethod.POST, request, this._messageConverters);
|
||||
HttpMessageResponseExtractor responseExtractor = new HttpMessageResponseExtractor();
|
||||
return this.Execute<HttpResponseMessage>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the response with no entity as <see cref="HttpResponseMessage"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>The HTTP response message with no entity.</returns>
|
||||
public HttpResponseMessage PostForMessage(string url, object request, IDictionary<string, string> uriVariables)
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
HttpMethod.POST, request, this._messageConverters);
|
||||
HttpMessageResponseExtractor responseExtractor = new HttpMessageResponseExtractor();
|
||||
return this.Execute<HttpResponseMessage>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new resource by POSTing the given object to the URI template,
|
||||
/// and returns the response with no entity as <see cref="HttpResponseMessage"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be POSTed, may be null.</param>
|
||||
/// <returns>The HTTP response message with no entity.</returns>
|
||||
public HttpResponseMessage PostForMessage(Uri url, object request)
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
HttpMethod.POST, request, this._messageConverters);
|
||||
HttpMessageResponseExtractor responseExtractor = new HttpMessageResponseExtractor();
|
||||
return this.Execute<HttpResponseMessage>(url, requestCallback, responseExtractor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create or update a resource by PUTting the given object to the URI.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be PUT, may be null.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
public void Put(string url, object request, params string[] uriVariables)
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
@@ -336,6 +657,20 @@ namespace Spring.Http.Rest
|
||||
this.Execute<object>(url, requestCallback, null, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create or update a resource by PUTting the given object to the URI.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be PUT, may be null.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
public void Put(string url, object request, IDictionary<string, string> uriVariables)
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
@@ -343,6 +678,14 @@ namespace Spring.Http.Rest
|
||||
this.Execute<object>(url, requestCallback, null, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create or update a resource by PUTting the given object to the URI.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The request parameter can be a <see cref="HttpRequestMessage"/> in order to add additional HTTP headers to the request.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="request">The Object to be PUT, may be null.</param>
|
||||
public void Put(Uri url, object request)
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
@@ -350,24 +693,53 @@ namespace Spring.Http.Rest
|
||||
this.Execute<object>(url, requestCallback, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete the resources at the specified URI.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
public void Delete(string url, params string[] uriVariables)
|
||||
{
|
||||
MethodRequestCallback requestCallback = new MethodRequestCallback(HttpMethod.DELETE);
|
||||
this.Execute<object>(url, requestCallback, null, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete the resources at the specified URI.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
public void Delete(string url, IDictionary<string, string> uriVariables)
|
||||
{
|
||||
MethodRequestCallback requestCallback = new MethodRequestCallback(HttpMethod.DELETE);
|
||||
this.Execute<object>(url, requestCallback, null, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete the resources at the specified URI.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL.</param>
|
||||
public void Delete(Uri url)
|
||||
{
|
||||
MethodRequestCallback requestCallback = new MethodRequestCallback(HttpMethod.DELETE);
|
||||
this.Execute<object>(url, requestCallback, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the value of the Allow header for the given URI.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>The value of the allow header.</returns>
|
||||
public IList<HttpMethod> OptionsForAllow(string url, params string[] uriVariables)
|
||||
{
|
||||
MethodRequestCallback requestCallback = new MethodRequestCallback(HttpMethod.OPTIONS);
|
||||
@@ -378,6 +750,15 @@ namespace Spring.Http.Rest
|
||||
return ParseAllowHeader(allow);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the value of the Allow header for the given URI.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>The value of the allow header.</returns>
|
||||
public IList<HttpMethod> OptionsForAllow(string url, IDictionary<string, string> uriVariables)
|
||||
{
|
||||
MethodRequestCallback requestCallback = new MethodRequestCallback(HttpMethod.OPTIONS);
|
||||
@@ -387,6 +768,11 @@ namespace Spring.Http.Rest
|
||||
return ParseAllowHeader(allow);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the value of the Allow header for the given URI.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <returns>The value of the allow header.</returns>
|
||||
public IList<HttpMethod> OptionsForAllow(Uri url)
|
||||
{
|
||||
MethodRequestCallback requestCallback = new MethodRequestCallback(HttpMethod.OPTIONS);
|
||||
@@ -396,6 +782,18 @@ namespace Spring.Http.Rest
|
||||
return ParseAllowHeader(allow);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the HTTP request to the given URI template, writing the given request message to the request,
|
||||
/// and returns the response as <see cref="HttpResponseMessage{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="requestMessage">The HTTP request message to write to the request.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
public HttpResponseMessage<T> Exchange<T>(string url, HttpRequestMessage requestMessage, params string[] uriVariables) where T : class
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(requestMessage, typeof(T), this._messageConverters);
|
||||
@@ -403,6 +801,18 @@ namespace Spring.Http.Rest
|
||||
return this.Execute<HttpResponseMessage<T>>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the HTTP request to the given URI template, writing the given request message to the request,
|
||||
/// and returns the response as <see cref="HttpResponseMessage{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="requestMessage">The HTTP request message to write to the request.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
public HttpResponseMessage<T> Exchange<T>(string url, HttpRequestMessage requestMessage, IDictionary<string, string> uriVariables) where T : class
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(requestMessage, typeof(T), this._messageConverters);
|
||||
@@ -410,6 +820,14 @@ namespace Spring.Http.Rest
|
||||
return this.Execute<HttpResponseMessage<T>>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the HTTP request to the given URI template, writing the given request message to the request,
|
||||
/// and returns the response as <see cref="HttpResponseMessage{T}"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="requestMessage">The HTTP request message to write to the request.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
public HttpResponseMessage<T> Exchange<T>(Uri url, HttpRequestMessage requestMessage) where T : class
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(requestMessage, typeof(T), this._messageConverters);
|
||||
@@ -417,6 +835,69 @@ namespace Spring.Http.Rest
|
||||
return this.Execute<HttpResponseMessage<T>>(url, requestCallback, responseExtractor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the HTTP request to the given URI template, writing the given request message to the request,
|
||||
/// and returns the response with no entity as <see cref="HttpResponseMessage"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="requestMessage">The HTTP request message to write to the request.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>The HTTP response message with no entity.</returns>
|
||||
public HttpResponseMessage Exchange(string url, HttpRequestMessage requestMessage, params string[] uriVariables)
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(requestMessage, this._messageConverters);
|
||||
HttpMessageResponseExtractor responseExtractor = new HttpMessageResponseExtractor();
|
||||
return this.Execute<HttpResponseMessage>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the HTTP request to the given URI template, writing the given request message to the request,
|
||||
/// and returns the response with no entity as <see cref="HttpResponseMessage"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </remarks>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="requestMessage">The HTTP request message to write to the request.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>The HTTP response message with no entity.</returns>
|
||||
public HttpResponseMessage Exchange(string url, HttpRequestMessage requestMessage, IDictionary<string, string> uriVariables)
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(requestMessage, this._messageConverters);
|
||||
HttpMessageResponseExtractor responseExtractor = new HttpMessageResponseExtractor();
|
||||
return this.Execute<HttpResponseMessage>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the HTTP request to the given URI template, writing the given request message to the request,
|
||||
/// and returns the response with no entity as <see cref="HttpResponseMessage"/>.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="requestMessage">The HTTP request message to write to the request.</param>
|
||||
/// <returns>The HTTP response message with no entity.</returns>
|
||||
public HttpResponseMessage Exchange(Uri url, HttpRequestMessage requestMessage)
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(requestMessage, this._messageConverters);
|
||||
HttpMessageResponseExtractor responseExtractor = new HttpMessageResponseExtractor();
|
||||
return this.Execute<HttpResponseMessage>(url, requestCallback, responseExtractor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the HTTP request to the given URI template, preparing the request with the
|
||||
/// <see cref="IRequestCallback"/>, and reading the response with an <see cref="IResponseExtractor{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given URI variables, if any.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="requestCallback">Object that prepares the request.</param>
|
||||
/// <param name="responseExtractor">Object that extracts the return value from the response.</param>
|
||||
/// <param name="uriVariables">The variables to expand the template.</param>
|
||||
/// <returns>An arbitrary object, as returned by the <see cref="IResponseExtractor{T}"/>.</returns>
|
||||
public T Execute<T>(string url, IRequestCallback requestCallback, IResponseExtractor<T> responseExtractor, params string[] uriVariables) where T : class
|
||||
{
|
||||
UriTemplate uriTemplate = new UriTemplate(url);
|
||||
@@ -424,6 +905,19 @@ namespace Spring.Http.Rest
|
||||
return this.DoExecute<T>(uri, requestCallback, responseExtractor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the HTTP request to the given URI template, preparing the request with the
|
||||
/// <see cref="IRequestCallback"/>, and reading the response with an <see cref="IResponseExtractor{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URI Template variables are expanded using the given dictionary.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="requestCallback">Object that prepares the request.</param>
|
||||
/// <param name="responseExtractor">Object that extracts the return value from the response.</param>
|
||||
/// <param name="uriVariables">The dictionary containing variables for the URI template.</param>
|
||||
/// <returns>An arbitrary object, as returned by the <see cref="IResponseExtractor{T}"/>.</returns>
|
||||
public T Execute<T>(string url, IRequestCallback requestCallback, IResponseExtractor<T> responseExtractor, IDictionary<string, string> uriVariables) where T : class
|
||||
{
|
||||
UriTemplate uriTemplate = new UriTemplate(url);
|
||||
@@ -431,6 +925,15 @@ namespace Spring.Http.Rest
|
||||
return this.DoExecute<T>(uri, requestCallback, responseExtractor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the HTTP request to the given URI template, preparing the request with the
|
||||
/// <see cref="IRequestCallback"/>, and reading the response with an <see cref="IResponseExtractor{T}"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="requestCallback">Object that prepares the request.</param>
|
||||
/// <param name="responseExtractor">Object that extracts the return value from the response.</param>
|
||||
/// <returns>An arbitrary object, as returned by the <see cref="IResponseExtractor{T}"/>.</returns>
|
||||
public T Execute<T>(Uri url, IRequestCallback requestCallback, IResponseExtractor<T> responseExtractor) where T : class
|
||||
{
|
||||
return this.DoExecute<T>(url, requestCallback, responseExtractor);
|
||||
@@ -438,30 +941,30 @@ namespace Spring.Http.Rest
|
||||
|
||||
#endregion
|
||||
|
||||
/**
|
||||
* Execute the given method on the provided URI. The {@link ClientHttpRequest} is processed using the {@link
|
||||
* RequestCallback}; the response with the {@link ResponseExtractor}.
|
||||
* @param url the fully-expanded URL to connect to
|
||||
* @param method the HTTP method to execute (GET, POST, etc.)
|
||||
* @param requestCallback object that prepares the request (can be <code>null</code>)
|
||||
* @param responseExtractor object that extracts the return value from the response (can be <code>null</code>)
|
||||
* @return an arbitrary object, as returned by the {@link ResponseExtractor}
|
||||
*/
|
||||
protected virtual T DoExecute<T>(Uri url, IRequestCallback requestCallback, IResponseExtractor<T> responseExtractor) where T : class
|
||||
/// <summary>
|
||||
/// Execute the HTTP request to the given URI, preparing the request with the
|
||||
/// <see cref="IRequestCallback"/>, and reading the response with an <see cref="IResponseExtractor{T}"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the response value.</typeparam>
|
||||
/// <param name="uri">The fully-expanded URI to connect to.</param>
|
||||
/// <param name="requestCallback">Object that prepares the request.</param>
|
||||
/// <param name="responseExtractor">Object that extracts the return value from the response.</param>
|
||||
/// <returns>An arbitrary object, as returned by the <see cref="IResponseExtractor{T}"/>.</returns>
|
||||
protected virtual T DoExecute<T>(Uri uri, IRequestCallback requestCallback, IResponseExtractor<T> responseExtractor) where T : class
|
||||
{
|
||||
HttpWebRequest request;
|
||||
HttpWebResponse response = null;
|
||||
|
||||
Uri finalUri = url;
|
||||
if (!url.IsAbsoluteUri)
|
||||
Uri finalUri = uri;
|
||||
if (!uri.IsAbsoluteUri)
|
||||
{
|
||||
if (this._baseAddress != null)
|
||||
{
|
||||
finalUri = new Uri(this._baseAddress, url);
|
||||
finalUri = new Uri(this._baseAddress, uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException(String.Format("'{0}' is not an absolute URI", url), "url");
|
||||
throw new ArgumentException(String.Format("'{0}' is not an absolute URI", uri), "uri");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,14 +22,17 @@ using System;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Spring.Util;
|
||||
using Spring.Http;
|
||||
using Spring.Http.Converters;
|
||||
|
||||
namespace Spring.Http.Rest.Support
|
||||
{
|
||||
/**
|
||||
* Request callback implementation that prepares the request's accept headers.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Request callback implementation that prepares the request's accept headers.
|
||||
/// </summary>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
public class AcceptHeaderRequestCallback : MethodRequestCallback
|
||||
{
|
||||
#region Logging
|
||||
@@ -38,9 +41,22 @@ namespace Spring.Http.Rest.Support
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The expected response body type.
|
||||
/// </summary>
|
||||
protected Type responseType;
|
||||
|
||||
/// <summary>
|
||||
/// The list of <see cref="IHttpMessageConverter"/> to use.
|
||||
/// </summary>
|
||||
protected IList<IHttpMessageConverter> messageConverters;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="AcceptHeaderRequestCallback"/>.
|
||||
/// </summary>
|
||||
/// <param name="method">The HTTP method.</param>
|
||||
/// <param name="responseType">The expected response body type.</param>
|
||||
/// <param name="messageConverters">The list of <see cref="IHttpMessageConverter"/> to use.</param>
|
||||
public AcceptHeaderRequestCallback(HttpMethod method, Type responseType, IList<IHttpMessageConverter> messageConverters) :
|
||||
base(method)
|
||||
{
|
||||
@@ -48,6 +64,12 @@ namespace Spring.Http.Rest.Support
|
||||
this.messageConverters = messageConverters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets called by <see cref="RestTemplate"/> with an opened <see cref="HttpWebRequest"/> to write data.
|
||||
/// Does not need to care about closing the request or about handling errors:
|
||||
/// this will all be handled by the <see cref="RestTemplate"/> class.
|
||||
/// </summary>
|
||||
/// <param name="request">The active HTTP request.</param>
|
||||
public override void DoWithRequest(HttpWebRequest request)
|
||||
{
|
||||
base.DoWithRequest(request);
|
||||
@@ -61,7 +83,7 @@ namespace Spring.Http.Rest.Support
|
||||
{
|
||||
foreach (MediaType supportedMediaType in messageConverter.SupportedMediaTypes)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(supportedMediaType.CharSet))
|
||||
if (StringUtils.HasText(supportedMediaType.CharSet))
|
||||
{
|
||||
allSupportedMediaTypes.Add(new MediaType(
|
||||
supportedMediaType.Type, supportedMediaType.Subtype));
|
||||
|
||||
@@ -22,11 +22,19 @@ using System.Net;
|
||||
|
||||
namespace Spring.Http.Rest.Support
|
||||
{
|
||||
/**
|
||||
* Response extractor that extracts the response {@link HttpHeaders}.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Response extractor that extracts the response HTTP headers.
|
||||
/// </summary>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
public class HeadersResponseExtractor : IResponseExtractor<WebHeaderCollection>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets called by <see cref="RestTemplate"/> with an opened <see cref="HttpWebResponse"/> to extract data.
|
||||
/// Does not need to care about closing the request or about handling errors:
|
||||
/// this will all be handled by the <see cref="RestTemplate"/> class.
|
||||
/// </summary>
|
||||
/// <param name="response">The active HTTP request.</param>
|
||||
public WebHeaderCollection ExtractData(HttpWebResponse response)
|
||||
{
|
||||
return response.Headers;
|
||||
|
||||
@@ -22,15 +22,16 @@ using System;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Spring.Util;
|
||||
using Spring.Http;
|
||||
using Spring.Http.Converters;
|
||||
|
||||
namespace Spring.Http.Rest.Support
|
||||
{
|
||||
/**
|
||||
* Request callback implementation that writes the given object to the request stream.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Request callback implementation that writes the given object to the request stream.
|
||||
/// </summary>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
public class HttpMessageRequestCallback : AcceptHeaderRequestCallback
|
||||
{
|
||||
#region Logging
|
||||
@@ -41,11 +42,24 @@ namespace Spring.Http.Rest.Support
|
||||
|
||||
private HttpRequestMessage requestMessage;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="HttpMessageRequestCallback"/>.
|
||||
/// </summary>
|
||||
/// <param name="method">The HTTP method.</param>
|
||||
/// <param name="requestBody">The object to write to the request.</param>
|
||||
/// <param name="messageConverters">The list of <see cref="IHttpMessageConverter"/> to use.</param>
|
||||
public HttpMessageRequestCallback(HttpMethod method, object requestBody, IList<IHttpMessageConverter> messageConverters) :
|
||||
this(method, requestBody, null, messageConverters)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="HttpMessageRequestCallback"/>.
|
||||
/// </summary>
|
||||
/// <param name="method">The HTTP method.</param>
|
||||
/// <param name="requestBody">The object to write to the request.</param>
|
||||
/// <param name="responseType">The expected response body type.</param>
|
||||
/// <param name="messageConverters">The list of <see cref="IHttpMessageConverter"/> to use.</param>
|
||||
public HttpMessageRequestCallback(HttpMethod method, object requestBody, Type responseType, IList<IHttpMessageConverter> messageConverters) :
|
||||
base(method, responseType, messageConverters)
|
||||
{
|
||||
@@ -60,17 +74,34 @@ namespace Spring.Http.Rest.Support
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="HttpMessageRequestCallback"/>.
|
||||
/// </summary>
|
||||
/// <param name="requestMessage">The HTTP request message.</param>
|
||||
/// <param name="messageConverters">The list of <see cref="IHttpMessageConverter"/> to use.</param>
|
||||
public HttpMessageRequestCallback(HttpRequestMessage requestMessage, IList<IHttpMessageConverter> messageConverters) :
|
||||
this(requestMessage, null, messageConverters)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="HttpMessageRequestCallback"/>.
|
||||
/// </summary>
|
||||
/// <param name="requestMessage">The HTTP request message.</param>
|
||||
/// <param name="responseType">The expected response body type.</param>
|
||||
/// <param name="messageConverters">The list of <see cref="IHttpMessageConverter"/> to use.</param>
|
||||
public HttpMessageRequestCallback(HttpRequestMessage requestMessage, Type responseType, IList<IHttpMessageConverter> messageConverters) :
|
||||
base(requestMessage.Method, responseType, messageConverters)
|
||||
{
|
||||
this.requestMessage = requestMessage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets called by <see cref="RestTemplate"/> with an opened <see cref="HttpWebRequest"/> to write data.
|
||||
/// Does not need to care about closing the request or about handling errors:
|
||||
/// this will all be handled by the <see cref="RestTemplate"/> class.
|
||||
/// </summary>
|
||||
/// <param name="request">The active HTTP request.</param>
|
||||
public override void DoWithRequest(HttpWebRequest request)
|
||||
{
|
||||
base.DoWithRequest(request);
|
||||
@@ -78,18 +109,26 @@ namespace Spring.Http.Rest.Support
|
||||
// headers
|
||||
if (requestMessage.Headers.Count > 0)
|
||||
{
|
||||
request.Headers.Add(requestMessage.Headers);
|
||||
foreach(string headerName in requestMessage.Headers)
|
||||
{
|
||||
// TODO : Check other special cases or create a HttpHeaders class
|
||||
// Special cases
|
||||
if (headerName == "Content-Type")
|
||||
{
|
||||
request.ContentType = requestMessage.Headers[HttpRequestHeader.ContentType];
|
||||
}
|
||||
else
|
||||
{
|
||||
request.Headers.Add(headerName, requestMessage.Headers[headerName]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// body
|
||||
if (requestMessage.Body != null)
|
||||
{
|
||||
object requestBody = requestMessage.Body;
|
||||
MediaType requestContentType = null;
|
||||
if (StringUtils.HasText(requestMessage.Headers[HttpRequestHeader.ContentType]))
|
||||
{
|
||||
requestContentType = MediaType.ParseMediaType(requestMessage.Headers[HttpRequestHeader.ContentType]);
|
||||
}
|
||||
MediaType requestContentType = MediaType.ParseMediaType(requestMessage.Headers[HttpRequestHeader.ContentType]);
|
||||
foreach (IHttpMessageConverter messageConverter in base.messageConverters)
|
||||
{
|
||||
if (messageConverter.CanWrite(requestBody.GetType(), requestContentType))
|
||||
|
||||
@@ -19,37 +19,24 @@
|
||||
#endregion
|
||||
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Spring.Util;
|
||||
using Spring.Http;
|
||||
using Spring.Http.Converters;
|
||||
|
||||
namespace Spring.Http.Rest.Support
|
||||
{
|
||||
/**
|
||||
* Response extractor for {@link HttpEntity}.
|
||||
*/
|
||||
public class HttpMessageResponseExtractor<T> : IResponseExtractor<HttpResponseMessage<T>> where T : class
|
||||
/// <summary>
|
||||
/// Response extractor that extracts the HTTP response message with no body.
|
||||
/// </summary>
|
||||
/// <author>Bruno Baia</author>
|
||||
public class HttpMessageResponseExtractor : IResponseExtractor<HttpResponseMessage>
|
||||
{
|
||||
private MessageConverterResponseExtractor<T> httpMessageConverterExtractor;
|
||||
|
||||
public HttpMessageResponseExtractor(IList<IHttpMessageConverter> messageConverters)
|
||||
/// <summary>
|
||||
/// Gets called by <see cref="RestTemplate"/> with an opened <see cref="HttpWebResponse"/> to extract data.
|
||||
/// Does not need to care about closing the request or about handling errors:
|
||||
/// this will all be handled by the <see cref="RestTemplate"/> class.
|
||||
/// </summary>
|
||||
/// <param name="response">The active HTTP request.</param>
|
||||
public HttpResponseMessage ExtractData(HttpWebResponse response)
|
||||
{
|
||||
httpMessageConverterExtractor = new MessageConverterResponseExtractor<T>(messageConverters);
|
||||
}
|
||||
|
||||
public HttpResponseMessage<T> ExtractData(HttpWebResponse response)
|
||||
{
|
||||
if (StringUtils.HasText(response.Headers[HttpResponseHeader.ContentType]))
|
||||
{
|
||||
T body = httpMessageConverterExtractor.ExtractData(response);
|
||||
return new HttpResponseMessage<T>(body, response.Headers, response.StatusCode, response.StatusDescription);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new HttpResponseMessage<T>(response.Headers, response.StatusCode, response.StatusDescription);
|
||||
}
|
||||
return new HttpResponseMessage(response.Headers, response.StatusCode, response.StatusDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Spring.Http;
|
||||
using Spring.Http.Converters;
|
||||
|
||||
namespace Spring.Http.Rest.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// Response extractor that extracts the HTTP response message with no body.
|
||||
/// </summary>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
public class HttpMessageResponseExtractor<T> : IResponseExtractor<HttpResponseMessage<T>> where T : class
|
||||
{
|
||||
private MessageConverterResponseExtractor<T> httpMessageConverterExtractor;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="HttpMessageResponseExtractor{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="messageConverters">The list of <see cref="IHttpMessageConverter"/> to use.</param>
|
||||
public HttpMessageResponseExtractor(IList<IHttpMessageConverter> messageConverters)
|
||||
{
|
||||
httpMessageConverterExtractor = new MessageConverterResponseExtractor<T>(messageConverters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets called by <see cref="RestTemplate"/> with an opened <see cref="HttpWebResponse"/> to extract data.
|
||||
/// Does not need to care about closing the request or about handling errors:
|
||||
/// this will all be handled by the <see cref="RestTemplate"/> class.
|
||||
/// </summary>
|
||||
/// <param name="response">The active HTTP request.</param>
|
||||
public HttpResponseMessage<T> ExtractData(HttpWebResponse response)
|
||||
{
|
||||
T body = httpMessageConverterExtractor.ExtractData(response);
|
||||
return new HttpResponseMessage<T>(body, response.Headers, response.StatusCode, response.StatusDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,14 +28,12 @@ using Spring.Http.Converters;
|
||||
|
||||
namespace Spring.Http.Rest.Support
|
||||
{
|
||||
/**
|
||||
* Response extractor that uses the given {@linkplain HttpMessageConverter entity converters} to convert the response
|
||||
* into a type <code>T</code>.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see RestTemplate
|
||||
* @since 3.0
|
||||
*/
|
||||
/// <summary>
|
||||
/// Response extractor that uses the given HTTP message converters to convert the response into a type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The response body type.</typeparam>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
public class MessageConverterResponseExtractor<T> : IResponseExtractor<T> where T : class
|
||||
{
|
||||
#region Logging
|
||||
@@ -46,25 +44,32 @@ namespace Spring.Http.Rest.Support
|
||||
|
||||
private IList<IHttpMessageConverter> messageConverters;
|
||||
|
||||
/**
|
||||
* Creates a new instance of the {@code HttpMessageConverterExtractor} with the given response type and message
|
||||
* converters. The given converters must support the response type.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="MessageConverterResponseExtractor{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="messageConverters">The list of <see cref="IHttpMessageConverter"/> to use.</param>
|
||||
public MessageConverterResponseExtractor(IList<IHttpMessageConverter> messageConverters)
|
||||
{
|
||||
this.messageConverters = messageConverters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets called by <see cref="RestTemplate"/> with an opened <see cref="HttpWebResponse"/> to extract data.
|
||||
/// Does not need to care about closing the request or about handling errors:
|
||||
/// this will all be handled by the <see cref="RestTemplate"/> class.
|
||||
/// </summary>
|
||||
/// <param name="response">The active HTTP request.</param>
|
||||
public T ExtractData(HttpWebResponse response)
|
||||
{
|
||||
if (!StringUtils.HasText(response.Headers[HttpResponseHeader.ContentType]))
|
||||
string contentType = response.Headers[HttpResponseHeader.ContentType];
|
||||
if (!StringUtils.HasText(contentType))
|
||||
{
|
||||
throw new RestClientException("Could not extract response: no Content-Type found");
|
||||
}
|
||||
MediaType contentType = MediaType.ParseMediaType(response.Headers[HttpResponseHeader.ContentType]);
|
||||
MediaType mediaType = MediaType.ParseMediaType(contentType);
|
||||
foreach(IHttpMessageConverter messageConverter in messageConverters)
|
||||
{
|
||||
if (messageConverter.CanRead(typeof(T), contentType))
|
||||
if (messageConverter.CanRead(typeof(T), mediaType))
|
||||
{
|
||||
#region Instrumentation
|
||||
|
||||
@@ -72,7 +77,7 @@ namespace Spring.Http.Rest.Support
|
||||
{
|
||||
LOG.Debug(String.Format(
|
||||
"Reading [{0}] as '{1}' using [{2}]",
|
||||
typeof(T).FullName, contentType, messageConverter));
|
||||
typeof(T).FullName, mediaType, messageConverter));
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -82,7 +87,7 @@ namespace Spring.Http.Rest.Support
|
||||
}
|
||||
throw new RestClientException(String.Format(
|
||||
"Could not extract response: no suitable HttpMessageConverter found for response type [{0}] and content type [{1}]",
|
||||
typeof(T).FullName, contentType));
|
||||
typeof(T).FullName, mediaType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,9 +25,10 @@ using Spring.Http;
|
||||
|
||||
namespace Spring.Http.Rest.Support
|
||||
{
|
||||
/**
|
||||
* Request callback implementation that sets the Http method.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Request callback implementation that sets the HTTP method.
|
||||
/// </summary>
|
||||
/// <author>Bruno Baia</author>
|
||||
public class MethodRequestCallback : IRequestCallback
|
||||
{
|
||||
#region Logging
|
||||
@@ -36,13 +37,26 @@ namespace Spring.Http.Rest.Support
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The HTTP method.
|
||||
/// </summary>
|
||||
protected HttpMethod method;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="MethodRequestCallback"/>.
|
||||
/// </summary>
|
||||
/// <param name="method">The HTTP method.</param>
|
||||
public MethodRequestCallback(HttpMethod method)
|
||||
{
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets called by <see cref="RestTemplate"/> with an opened <see cref="HttpWebRequest"/> to write data.
|
||||
/// Does not need to care about closing the request or about handling errors:
|
||||
/// this will all be handled by the <see cref="RestTemplate"/> class.
|
||||
/// </summary>
|
||||
/// <param name="request">The active HTTP request.</param>
|
||||
public virtual void DoWithRequest(HttpWebRequest request)
|
||||
{
|
||||
#region Instrumentation
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Http\Converters\Feed\Atom10FeedHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Feed\AbstractFeedHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Feed\RssFeedHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Feed\Rss20FeedHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Json\JsonHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Xml\AbstractXmlHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Xml\XElementHttpMessageConverter.cs" />
|
||||
@@ -109,9 +109,11 @@
|
||||
<Compile Include="Http\Converters\Xml\DataContractHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\DefaultHttpWebRequestFactory.cs" />
|
||||
<Compile Include="Http\HttpResponseMessage.cs" />
|
||||
<Compile Include="Http\HttpResponseMessage`1.cs" />
|
||||
<Compile Include="Http\IHttpWebRequestFactory.cs" />
|
||||
<Compile Include="Http\HttpRequestMessage.cs" />
|
||||
<Compile Include="Http\Rest\Support\AcceptHeaderRequestCallback.cs" />
|
||||
<Compile Include="Http\Rest\Support\HttpMessageResponseExtractor`1.cs" />
|
||||
<Compile Include="Http\Rest\Support\MethodRequestCallback.cs" />
|
||||
<Compile Include="Http\Rest\Support\HttpMessageRequestCallback.cs" />
|
||||
<Compile Include="Http\Rest\Support\HeadersResponseExtractor.cs" />
|
||||
@@ -128,14 +130,10 @@
|
||||
<Compile Include="Http\Rest\RestClientException.cs" />
|
||||
<Compile Include="Http\Rest\RestTemplate.cs" />
|
||||
<Compile Include="Http\Converters\StringHttpMessageConverter.cs" />
|
||||
<Compile Include="Util\AssertUtils.cs" />
|
||||
<Compile Include="Util\StringUtils.cs" />
|
||||
<Compile Include="Util\UriTemplate.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Spring.Core\Spring.Core.2008.csproj">
|
||||
<Project>{710961A3-0DF4-49E4-A26E-F5B9C044AC84}</Project>
|
||||
<Name>Spring.Core.2008</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
|
||||
@@ -111,7 +111,9 @@
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Http\Converters\Feed\Rss20FeedHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\HttpResponseMessage.cs" />
|
||||
<Compile Include="Http\HttpResponseMessage`1.cs" />
|
||||
<Compile Include="Http\DefaultHttpWebRequestFactory.cs" />
|
||||
<Compile Include="Http\Converters\AbstractHttpMessageConverter.cs">
|
||||
<SubType>Code</SubType>
|
||||
@@ -121,7 +123,6 @@
|
||||
</Compile>
|
||||
<Compile Include="Http\Converters\Feed\AbstractFeedHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Feed\Atom10FeedHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Feed\RssFeedHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\IHttpMessageConverter.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
@@ -144,19 +145,18 @@
|
||||
<Compile Include="Http\Rest\RestClientException.cs" />
|
||||
<Compile Include="Http\Rest\RestTemplate.cs" />
|
||||
<Compile Include="Http\Rest\Support\AcceptHeaderRequestCallback.cs" />
|
||||
<Compile Include="Http\Rest\Support\HttpMessageResponseExtractor`1.cs" />
|
||||
<Compile Include="Http\Rest\Support\HeadersResponseExtractor.cs" />
|
||||
<Compile Include="Http\Rest\Support\HttpMessageRequestCallback.cs" />
|
||||
<Compile Include="Http\Rest\Support\HttpMessageResponseExtractor.cs" />
|
||||
<Compile Include="Http\Rest\Support\MessageConverterResponseExtractor.cs" />
|
||||
<Compile Include="Http\Rest\Support\MethodRequestCallback.cs" />
|
||||
<Compile Include="Util\AssertUtils.cs" />
|
||||
<Compile Include="Util\StringUtils.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Util\UriTemplate.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Spring.Core\Spring.Core.2010.csproj">
|
||||
<Project>{710961A3-0DF4-49E4-A26E-F5B9C044AC84}</Project>
|
||||
<Name>Spring.Core.2010</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
<Visible>False</Visible>
|
||||
|
||||
121
src/Spring/Spring.Http/Util/AssertUtils.cs
Normal file
121
src/Spring/Spring.Http/Util/AssertUtils.cs
Normal file
@@ -0,0 +1,121 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Spring.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Assertion utility methods that simplify things such as argument checks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Not intended to be used directly by applications.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
/// <author>Erich Eichinger</author>
|
||||
internal sealed class AssertUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks the value of the supplied <paramref name="argument"/> and throws an
|
||||
/// <see cref="System.ArgumentNullException"/> if it is <see langword="null"/>.
|
||||
/// </summary>
|
||||
/// <param name="argument">The object to check.</param>
|
||||
/// <param name="name">The argument name.</param>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// If the supplied <paramref name="argument"/> is <see langword="null"/>.
|
||||
/// </exception>
|
||||
internal static void ArgumentNotNull(object argument, string name)
|
||||
{
|
||||
if (argument == null)
|
||||
{
|
||||
throw new ArgumentNullException (name,
|
||||
String.Format(CultureInfo.InvariantCulture, "Argument '{0}' cannot be null.", name));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks the value of the supplied <paramref name="argument"/> and throws an
|
||||
/// <see cref="System.ArgumentNullException"/> if it is <see langword="null"/>.
|
||||
/// </summary>
|
||||
/// <param name="argument">The object to check.</param>
|
||||
/// <param name="name">The argument name.</param>
|
||||
/// <param name="message">
|
||||
/// An arbitrary message that will be passed to any thrown
|
||||
/// <see cref="System.ArgumentNullException"/>.
|
||||
/// </param>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// If the supplied <paramref name="argument"/> is <see langword="null"/>.
|
||||
/// </exception>
|
||||
internal static void ArgumentNotNull(object argument, string name, string message)
|
||||
{
|
||||
if (argument == null)
|
||||
{
|
||||
throw new ArgumentNullException(name, message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks the value of the supplied string <paramref name="argument"/> and throws an
|
||||
/// <see cref="System.ArgumentNullException"/> if it is <see langword="null"/> or
|
||||
/// contains only whitespace character(s).
|
||||
/// </summary>
|
||||
/// <param name="argument">The string to check.</param>
|
||||
/// <param name="name">The argument name.</param>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// If the supplied <paramref name="argument"/> is <see langword="null"/> or
|
||||
/// contains only whitespace character(s).
|
||||
/// </exception>
|
||||
internal static void ArgumentHasText(string argument, string name)
|
||||
{
|
||||
if (!StringUtils.HasText(argument))
|
||||
{
|
||||
throw new ArgumentNullException(name,
|
||||
String.Format (CultureInfo.InvariantCulture,
|
||||
"Argument '{0}' cannot be null or resolve to an empty string : '{1}'.", name, argument));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks the value of the supplied string <paramref name="argument"/> and throws an
|
||||
/// <see cref="System.ArgumentNullException"/> if it is <see langword="null"/> or
|
||||
/// contains only whitespace character(s).
|
||||
/// </summary>
|
||||
/// <param name="argument">The string to check.</param>
|
||||
/// <param name="name">The argument name.</param>
|
||||
/// <param name="message">
|
||||
/// An arbitrary message that will be passed to any thrown
|
||||
/// <see cref="System.ArgumentNullException"/>.
|
||||
/// </param>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// If the supplied <paramref name="argument"/> is <see langword="null"/> or
|
||||
/// contains only whitespace character(s).
|
||||
/// </exception>
|
||||
internal static void ArgumentHasText(string argument, string name, string message)
|
||||
{
|
||||
if (!StringUtils.HasText(argument))
|
||||
{
|
||||
throw new ArgumentNullException(name, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
103
src/Spring/Spring.Http/Util/StringUtils.cs
Normal file
103
src/Spring/Spring.Http/Util/StringUtils.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace Spring.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Miscellaneous <see cref="System.String"/> utility methods.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Mainly for internal use within the framework.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Rod Johnson</author>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Keith Donald</author>
|
||||
/// <author>Aleksandar Seovic (.NET)</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
/// <author>Rick Evans (.NET)</author>
|
||||
/// <author>Erich Eichinger (.NET)</author>
|
||||
internal sealed class StringUtils
|
||||
{
|
||||
/// <summary>Checks if a string has length.</summary>
|
||||
/// <param name="target">
|
||||
/// The string to check, may be <see langword="null"/>.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the string has length and is not
|
||||
/// <see langword="null"/>.
|
||||
/// </returns>
|
||||
/// <example>
|
||||
/// <code lang="C#">
|
||||
/// StringUtils.HasLength(null) = false
|
||||
/// StringUtils.HasLength("") = false
|
||||
/// StringUtils.HasLength(" ") = true
|
||||
/// StringUtils.HasLength("Hello") = true
|
||||
/// </code>
|
||||
/// </example>
|
||||
internal static bool HasLength(string target)
|
||||
{
|
||||
return (target != null && target.Length > 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a <see cref="System.String"/> has text.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// More specifically, returns <see langword="true"/> if the string is
|
||||
/// not <see langword="null"/>, it's <see cref="String.Length"/> is >
|
||||
/// zero <c>(0)</c>, and it has at least one non-whitespace character.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <param name="target">
|
||||
/// The string to check, may be <see langword="null"/>.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the <paramref name="target"/> is not
|
||||
/// <see langword="null"/>,
|
||||
/// <see cref="String.Length"/> > zero <c>(0)</c>, and does not consist
|
||||
/// solely of whitespace.
|
||||
/// </returns>
|
||||
/// <example>
|
||||
/// <code language="C#">
|
||||
/// StringUtils.HasText(null) = false
|
||||
/// StringUtils.HasText("") = false
|
||||
/// StringUtils.HasText(" ") = false
|
||||
/// StringUtils.HasText("12345") = true
|
||||
/// StringUtils.HasText(" 12345 ") = true
|
||||
/// </code>
|
||||
/// </example>
|
||||
internal static bool HasText(string target)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HasLength(target.Trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,16 +28,13 @@ namespace Spring.Util
|
||||
// TODO : Check .NET 3.5 class
|
||||
// TODO : Back to original Java behavior Expand(params string[]) method ?
|
||||
|
||||
/**
|
||||
* Represents a URI template. An URI template is a URI-like String that contained variables marked of in braces
|
||||
* (<code>{</code>, <code>}</code>), which can be expanded to produce a URI. <p>See {@link #expand(Map)},
|
||||
* {@link #expand(Object[])}, and {@link #match(String)} for example usages.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see <a href="http://bitworking.org/projects/URI-Templates/">URI Templates</a>
|
||||
*/
|
||||
/// <summary>
|
||||
/// Represents a URI template. An URI template is a URI-like String that contained variables
|
||||
/// marked of in braces {}, which can be expanded to produce a URI.
|
||||
/// </summary>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
public class UriTemplate
|
||||
{
|
||||
/** Captures URI template variable names. */
|
||||
@@ -54,11 +51,18 @@ namespace Spring.Util
|
||||
private string[] variableNames;
|
||||
private Regex matchRegex;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the names of the variables in the template, in order.
|
||||
/// </summary>
|
||||
public string[] VariableNames
|
||||
{
|
||||
get { return this.variableNames; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="UriTemplate"/> with the given URI String.
|
||||
/// </summary>
|
||||
/// <param name="uriTemplate">The URI template string.</param>
|
||||
public UriTemplate(string uriTemplate)
|
||||
{
|
||||
this.uriTemplate = uriTemplate;
|
||||
@@ -67,6 +71,23 @@ namespace Spring.Util
|
||||
this.matchRegex = parser.GetMatchRegex();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given the dictionary of variables, expands this template into a full URI.
|
||||
/// The dictionary keys represent variable names, the dicitonary values variable values.
|
||||
/// The order of variables is not significant.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
|
||||
/// IDictionary<string, string> uriVariables = new Dictionary<String, String>();
|
||||
/// uriVariables.Add("booking", "42");
|
||||
/// uriVariables.Add("hotel", "1");
|
||||
/// Console.Out.WriteLine(template.Expand(uriVariables));
|
||||
/// </code>
|
||||
/// will print: <blockquote>http://example.com/hotels/1/bookings/42</blockquote>
|
||||
/// </example>
|
||||
/// <param name="uriVariables">The dictionary of URI variables.</param>
|
||||
/// <returns>The expanded URI</returns>
|
||||
public Uri Expand(IDictionary<string, string> uriVariables)
|
||||
{
|
||||
if (uriVariables.Count != this.variableNames.Length)
|
||||
@@ -105,6 +126,19 @@ namespace Spring.Util
|
||||
//return Expand(uriVariableValues);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given an array of variables, expands this template into a full URI.
|
||||
/// The array represent variable values. The order of variables is significant.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
|
||||
/// Console.Out.WriteLine(template.Expand("1", "42"));
|
||||
/// </code>
|
||||
/// will print: <blockquote>http://example.com/hotels/1/bookings/42</blockquote>
|
||||
/// </example>
|
||||
/// <param name="uriVariableValues">The array of URI variables.</param>
|
||||
/// <returns>The expanded URI</returns>
|
||||
public Uri Expand(params string[] uriVariableValues)
|
||||
{
|
||||
if (uriVariableValues.Length != this.variableNames.Length)
|
||||
@@ -123,11 +157,11 @@ namespace Spring.Util
|
||||
return new Uri(uri, UriKind.RelativeOrAbsolute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether the given URI matches this template.
|
||||
* @param uri the URI to match to
|
||||
* @return <code>true</code> if it matches; <code>false</code> otherwise
|
||||
*/
|
||||
/// <summary>
|
||||
/// Indicates whether the given URI matches this template.
|
||||
/// </summary>
|
||||
/// <param name="uri">The URI to match to.</param>
|
||||
/// <returns><see langword="true"/> if it matches; otherwise <see langword="false"/></returns>
|
||||
public bool Matches(string uri)
|
||||
{
|
||||
if (uri == null)
|
||||
@@ -137,14 +171,19 @@ namespace Spring.Util
|
||||
return this.matchRegex.IsMatch(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the given URI to a map of variable values. Keys in the returned map are variable names, values are variable
|
||||
* values, as occurred in the given URI. <p>Example: <pre class="code"> UriTemplate template = new
|
||||
* UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}"); System.out.println(template.match("http://example.com/hotels/1/bookings/42"));
|
||||
* </pre> will print: <blockquote><code>{hotel=1, booking=42}</code></blockquote>
|
||||
* @param uri the URI to match to
|
||||
* @return a map of variable values
|
||||
*/
|
||||
/// <summary>
|
||||
/// Match the given URI to a dictionary of variable values. Keys in the returned map are variable names,
|
||||
/// values are variable values, as occurred in the given URI
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
|
||||
/// Console.Out.WriteLine(template.Match("http://example.com/hotels/1/bookings/42"));
|
||||
/// </code>
|
||||
/// will print: <blockquote>{hotel=1, booking=42}</blockquote>
|
||||
/// </example>
|
||||
/// <param name="uri">The URI to match to.</param>
|
||||
/// <returns>A dictionary of variable values.</returns>
|
||||
public IDictionary<string, string> Match(string uri)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(uri, "uri");
|
||||
@@ -158,6 +197,12 @@ namespace Spring.Util
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object."/>
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object."/>.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return this.uriTemplate;
|
||||
|
||||
@@ -49,13 +49,18 @@ namespace Spring.Http.Converters
|
||||
public void CanRead()
|
||||
{
|
||||
Assert.IsTrue(converter.CanRead(typeof(byte[]), new MediaType("application", "octet-stream")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(byte[]), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanWrite(typeof(byte[]), MediaType.ALL));
|
||||
Assert.IsFalse(converter.CanRead(typeof(string), new MediaType("application", "octet-stream")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanWrite()
|
||||
{
|
||||
Assert.IsTrue(converter.CanWrite(typeof(byte[]), new MediaType("application", "octet-stream")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(byte[]), new MediaType("application", "octet-stream")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(byte[]), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanWrite(typeof(byte[]), MediaType.ALL));
|
||||
Assert.IsFalse(converter.CanRead(typeof(string), new MediaType("application", "octet-stream")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -64,8 +69,8 @@ namespace Spring.Http.Converters
|
||||
byte[] body = new byte[] { 0x1, 0x2 };
|
||||
|
||||
HttpWebResponse webResponse = mocks.CreateMock<HttpWebResponse>();
|
||||
Expect.Call<Stream>(webResponse.GetResponseStream()).Return(new MemoryStream(body)).Repeat.Once();
|
||||
Expect.Call<long>(webResponse.ContentLength).Return(2).Repeat.Once();
|
||||
Expect.Call<Stream>(webResponse.GetResponseStream()).Return(new MemoryStream(body));
|
||||
Expect.Call<long>(webResponse.ContentLength).Return(2);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
@@ -80,20 +85,23 @@ namespace Spring.Http.Converters
|
||||
[Test]
|
||||
public void Write()
|
||||
{
|
||||
MemoryStream requestStream = new MemoryStream();
|
||||
|
||||
byte[] body = new byte[] { 0x1, 0x2 };
|
||||
|
||||
HttpWebRequest webRequest = WebRequest.Create("http://localhost") as HttpWebRequest;
|
||||
webRequest.Method = "POST";
|
||||
|
||||
HttpWebRequest webRequest = mocks.CreateMock<HttpWebRequest>();
|
||||
Expect.Call(webRequest.ContentType = "application/octet-stream").PropertyBehavior();
|
||||
Expect.Call(webRequest.ContentLength = 2).PropertyBehavior();
|
||||
Expect.Call<Stream>(webRequest.GetRequestStream()).Return(requestStream);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
converter.Write(body, null, webRequest);
|
||||
|
||||
using (Stream postStream = webRequest.GetRequestStream())
|
||||
{
|
||||
//Assert.AreEqual(body.Length, postStream.Length, "Invalid result");
|
||||
}
|
||||
|
||||
Assert.AreEqual(new MediaType("application", "octet-stream"), MediaType.ParseMediaType(webRequest.ContentType), "Invalid content-type");
|
||||
Assert.AreEqual(2, webRequest.ContentLength, "Invalid content-length");
|
||||
byte[] result = requestStream.ToArray();
|
||||
Assert.AreEqual(body, result, "Invalid result");
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
#if NET_3_5
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
using System.ServiceModel.Syndication;
|
||||
|
||||
using NUnit.Framework;
|
||||
using Rhino.Mocks;
|
||||
|
||||
namespace Spring.Http.Converters.Feed
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests for the Atom10FeedHttpMessageConverter class.
|
||||
/// </summary>
|
||||
/// <author>Bruno Baia</author>
|
||||
[TestFixture]
|
||||
public class Atom10FeedHttpMessageConverterTests
|
||||
{
|
||||
private Atom10FeedHttpMessageConverter converter;
|
||||
private MockRepository mocks;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
mocks = new MockRepository();
|
||||
converter = new Atom10FeedHttpMessageConverter();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanRead()
|
||||
{
|
||||
Assert.IsTrue(converter.CanRead(typeof(SyndicationFeed), new MediaType("application", "atom+xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(SyndicationItem), new MediaType("application", "atom+xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(SyndicationFeed), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(SyndicationFeed), new MediaType("text", "xml")));
|
||||
Assert.IsFalse(converter.CanRead(typeof(string), new MediaType("application", "atom+xml")));
|
||||
Assert.IsFalse(converter.CanRead(typeof(SyndicationFeed), new MediaType("text", "plain")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanWrite()
|
||||
{
|
||||
Assert.IsTrue(converter.CanRead(typeof(SyndicationFeed), new MediaType("application", "atom+xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(SyndicationItem), new MediaType("application", "atom+xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(SyndicationFeed), new MediaType("text", "xml")));
|
||||
Assert.IsFalse(converter.CanRead(typeof(string), new MediaType("application", "atom+xml")));
|
||||
Assert.IsFalse(converter.CanRead(typeof(SyndicationFeed), new MediaType("text", "plain")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Read()
|
||||
{
|
||||
DateTime now = DateTime.Now;
|
||||
|
||||
string body = String.Format("<feed xmlns=\"http://www.w3.org/2005/Atom\"><title type=\"text\">Test Feed</title><subtitle type=\"text\">This is a test feed</subtitle><id>Atom10FeedHttpMessageConverterTests.Write</id><rights type=\"text\">Copyright 2010</rights><updated>{0}</updated><author><name>Bruno Baïa</name><uri>http://www.springframework.net/bbaia</uri><email>bruno.baia@springframework.net</email></author><link rel=\"alternate\" href=\"http://www.springframework.net/Feed\" /></feed>",
|
||||
now.ToString("yyyy-MM-ddTHH:mm:sszzz", CultureInfo.InvariantCulture));
|
||||
|
||||
HttpWebResponse webResponse = mocks.CreateMock<HttpWebResponse>();
|
||||
Expect.Call<Stream>(webResponse.GetResponseStream()).Return(new MemoryStream(Encoding.UTF8.GetBytes(body)));
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
SyndicationFeed result = converter.Read<SyndicationFeed>(webResponse);
|
||||
Assert.IsNotNull(result, "Invalid result");
|
||||
Assert.AreEqual("Atom10FeedHttpMessageConverterTests.Write", result.Id, "Invalid result");
|
||||
Assert.AreEqual("Test Feed", result.Title.Text, "Invalid result");
|
||||
Assert.AreEqual("This is a test feed", result.Description.Text, "Invalid result");
|
||||
Assert.IsTrue(result.Links.Count == 1, "Invalid result");
|
||||
Assert.AreEqual(new Uri("http://www.springframework.net/Feed"), result.Links[0].Uri, "Invalid result");
|
||||
Assert.AreEqual("Copyright 2010", result.Copyright.Text, "Invalid result");
|
||||
Assert.IsTrue(result.Authors.Count == 1, "Invalid result");
|
||||
Assert.AreEqual("Bruno Baïa", result.Authors[0].Name, "Invalid result");
|
||||
Assert.AreEqual("bruno.baia@springframework.net", result.Authors[0].Email, "Invalid result");
|
||||
Assert.AreEqual("http://www.springframework.net/bbaia", result.Authors[0].Uri, "Invalid result");
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Write()
|
||||
{
|
||||
MemoryStream requestStream = new MemoryStream();
|
||||
|
||||
DateTime now = DateTime.Now;
|
||||
|
||||
string expectedBody = String.Format("<feed xmlns=\"http://www.w3.org/2005/Atom\"><title type=\"text\">Test Feed</title><subtitle type=\"text\">This is a test feed</subtitle><id>Atom10FeedHttpMessageConverterTests.Write</id><rights type=\"text\">Copyright 2010</rights><updated>{0}</updated><author><name>Bruno Baïa</name><uri>http://www.springframework.net/bbaia</uri><email>bruno.baia@springframework.net</email></author><link rel=\"alternate\" href=\"http://www.springframework.net/Feed\" /></feed>",
|
||||
now.ToString("yyyy-MM-ddTHH:mm:sszzz", CultureInfo.InvariantCulture));
|
||||
|
||||
SyndicationFeed body = new SyndicationFeed("Test Feed", "This is a test feed", new Uri("http://www.springframework.net/Feed"), "Atom10FeedHttpMessageConverterTests.Write", now);
|
||||
SyndicationPerson sp = new SyndicationPerson("bruno.baia@springframework.net", "Bruno Baïa", "http://www.springframework.net/bbaia");
|
||||
body.Authors.Add(sp);
|
||||
body.Copyright = new TextSyndicationContent("Copyright 2010");
|
||||
|
||||
HttpWebRequest webRequest = mocks.CreateMock<HttpWebRequest>();
|
||||
Expect.Call(webRequest.ContentType = "application/atom+xml").PropertyBehavior();
|
||||
Expect.Call(webRequest.ContentLength = 1337).PropertyBehavior();
|
||||
Expect.Call<Stream>(webRequest.GetRequestStream()).Return(requestStream);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
converter.Write(body, null, webRequest);
|
||||
|
||||
byte[] result = requestStream.ToArray();
|
||||
Assert.AreEqual(expectedBody, Encoding.UTF8.GetString(result), "Invalid result");
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,171 @@
|
||||
#if NET_4_0
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Web;
|
||||
using System.ServiceModel.Syndication;
|
||||
|
||||
using Spring.Http.Rest;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Spring.Http.Converters.Feed
|
||||
{
|
||||
/// <summary>
|
||||
/// Integration tests for the SyndicationFeed based IHttpMessageConverter class.
|
||||
/// </summary>
|
||||
/// <author>Bruno Baia</author>
|
||||
[TestFixture]
|
||||
public class FeedHttpMessageConverterIntegrationTests
|
||||
{
|
||||
#region Logging
|
||||
|
||||
private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(FeedHttpMessageConverterIntegrationTests));
|
||||
|
||||
#endregion
|
||||
|
||||
private WebServiceHost webServiceHost;
|
||||
private string uri = "http://localhost:1337";
|
||||
private RestTemplate template;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
template = new RestTemplate(uri);
|
||||
template.MessageConverters = new List<IHttpMessageConverter>();
|
||||
//template.MessageConverters.Add(new StringHttpMessageConverter()); // for debugging purpose
|
||||
|
||||
webServiceHost = new WebServiceHost(typeof(TestService), new Uri(uri));
|
||||
webServiceHost.Open();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDownClass()
|
||||
{
|
||||
webServiceHost.Close();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Rss20GetForObject()
|
||||
{
|
||||
template.MessageConverters.Add(new Rss20FeedHttpMessageConverter());
|
||||
|
||||
SyndicationFeed result = template.GetForObject<SyndicationFeed>("feed");
|
||||
Assert.IsNotNull(result, "Invalid content");
|
||||
Assert.AreEqual("Test Feed", result.Title.Text, "Invalid content");
|
||||
Assert.AreEqual("This is a test feed", result.Description.Text, "Invalid content");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Rss20PostForMessage()
|
||||
{
|
||||
template.MessageConverters.Add(new Rss20FeedHttpMessageConverter());
|
||||
|
||||
SyndicationItem item = new SyndicationItem("Bruno's item", "Bruno's content", null);
|
||||
|
||||
HttpResponseMessage result = template.PostForMessage("feed/entry", item);
|
||||
Assert.IsNull(result.Body, "Invalid content");
|
||||
Assert.AreEqual(HttpStatusCode.Created, result.StatusCode, "Invalid status code");
|
||||
Assert.AreEqual("Syndication item added with title 'Bruno's item'", result.StatusDescription, "Invalid status description");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Atom10GetForObject()
|
||||
{
|
||||
template.MessageConverters.Add(new Atom10FeedHttpMessageConverter());
|
||||
|
||||
SyndicationFeed result = template.GetForObject<SyndicationFeed>("feed/?format=atom");
|
||||
Assert.IsNotNull(result, "Invalid content");
|
||||
Assert.AreEqual("Test Feed", result.Title.Text, "Invalid content");
|
||||
Assert.AreEqual("This is a test feed", result.Description.Text, "Invalid content");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Atom10PostForMessage()
|
||||
{
|
||||
template.MessageConverters.Add(new Atom10FeedHttpMessageConverter());
|
||||
|
||||
SyndicationItem item = new SyndicationItem("Bruno's item", "Bruno's content", null);
|
||||
|
||||
HttpResponseMessage result = template.PostForMessage("feed/entry", item);
|
||||
Assert.IsNull(result.Body, "Invalid content");
|
||||
Assert.AreEqual(HttpStatusCode.Created, result.StatusCode, "Invalid status code");
|
||||
Assert.AreEqual("Syndication item added with title 'Bruno's item'", result.StatusDescription, "Invalid status description");
|
||||
}
|
||||
|
||||
#region REST test service
|
||||
|
||||
[ServiceContract]
|
||||
[ServiceKnownType(typeof(Atom10FeedFormatter))]
|
||||
[ServiceKnownType(typeof(Rss20FeedFormatter))]
|
||||
[ServiceKnownType(typeof(Atom10ItemFormatter))]
|
||||
[ServiceKnownType(typeof(Rss20ItemFormatter))]
|
||||
public class TestService
|
||||
{
|
||||
[WebGet(UriTemplate = "feed/", BodyStyle = WebMessageBodyStyle.Bare)]
|
||||
public SyndicationFeedFormatter CreateFeed()
|
||||
{
|
||||
// Create a new Syndication Feed.
|
||||
SyndicationFeed feed = new SyndicationFeed("Test Feed", "This is a test feed", null);
|
||||
List<SyndicationItem> items = new List<SyndicationItem>();
|
||||
|
||||
// Create a new Syndication Item.
|
||||
SyndicationItem item = new SyndicationItem("An item", "Item content", null);
|
||||
items.Add(item);
|
||||
feed.Items = items;
|
||||
|
||||
// Return ATOM or RSS based on uri
|
||||
// rss -> http://localhost:1337/feed/
|
||||
// atom -> http://localhost:1337/feed/?format=atom
|
||||
string query = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters["format"];
|
||||
SyndicationFeedFormatter formatter = null;
|
||||
if (query == "atom")
|
||||
{
|
||||
formatter = new Atom10FeedFormatter(feed);
|
||||
}
|
||||
else
|
||||
{
|
||||
formatter = new Rss20FeedFormatter(feed);
|
||||
}
|
||||
|
||||
return formatter;
|
||||
}
|
||||
|
||||
[WebInvoke(UriTemplate = "feed/entry")]
|
||||
public void AddEntry(SyndicationItemFormatter item)
|
||||
{
|
||||
WebOperationContext context = WebOperationContext.Current;
|
||||
|
||||
// Add entry
|
||||
// ..
|
||||
|
||||
context.OutgoingResponse.StatusCode = HttpStatusCode.Created;
|
||||
context.OutgoingResponse.StatusDescription = String.Format("Syndication item added with title '{0}'", item.Item.Title.Text);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,131 @@
|
||||
#if NET_3_5
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
using System.ServiceModel.Syndication;
|
||||
|
||||
using NUnit.Framework;
|
||||
using Rhino.Mocks;
|
||||
|
||||
namespace Spring.Http.Converters.Feed
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests for the Rss20FeedHttpMessageConverter class.
|
||||
/// </summary>
|
||||
/// <author>Bruno Baia</author>
|
||||
[TestFixture]
|
||||
public class Rss20FeedHttpMessageConverterTests
|
||||
{
|
||||
private Rss20FeedHttpMessageConverter converter;
|
||||
private MockRepository mocks;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
mocks = new MockRepository();
|
||||
converter = new Rss20FeedHttpMessageConverter();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanRead()
|
||||
{
|
||||
Assert.IsTrue(converter.CanRead(typeof(SyndicationFeed), new MediaType("application", "rss+xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(SyndicationItem), new MediaType("application", "rss+xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(SyndicationFeed), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(SyndicationFeed), new MediaType("text", "xml")));
|
||||
Assert.IsFalse(converter.CanRead(typeof(string), new MediaType("application", "rss+xml")));
|
||||
Assert.IsFalse(converter.CanRead(typeof(SyndicationFeed), new MediaType("text", "plain")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanWrite()
|
||||
{
|
||||
Assert.IsTrue(converter.CanRead(typeof(SyndicationFeed), new MediaType("application", "rss+xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(SyndicationItem), new MediaType("application", "rss+xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(SyndicationFeed), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(SyndicationFeed), new MediaType("text", "xml")));
|
||||
Assert.IsFalse(converter.CanRead(typeof(string), new MediaType("application", "rss+xml")));
|
||||
Assert.IsFalse(converter.CanRead(typeof(SyndicationFeed), new MediaType("text", "plain")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Read()
|
||||
{
|
||||
DateTime now = DateTime.Now;
|
||||
|
||||
string body = String.Format("<rss xmlns:a10=\"http://www.w3.org/2005/Atom\" version=\"2.0\"><channel><title>Test Feed</title><link>http://www.springframework.net/Feed</link><description>This is a test feed</description><copyright>Copyright 2010</copyright><managingEditor>bruno.baia@springframework.net</managingEditor><lastBuildDate>{0}</lastBuildDate><a10:id>Atom10FeedHttpMessageConverterTests.Write</a10:id></channel></rss>",
|
||||
now.ToString("ddd, dd MMM yyyy HH:mm:ss zzz", CultureInfo.InvariantCulture).Remove(29, 1));
|
||||
|
||||
HttpWebResponse webResponse = mocks.CreateMock<HttpWebResponse>();
|
||||
Expect.Call<Stream>(webResponse.GetResponseStream()).Return(new MemoryStream(Encoding.UTF8.GetBytes(body)));
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
SyndicationFeed result = converter.Read<SyndicationFeed>(webResponse);
|
||||
Assert.IsNotNull(result, "Invalid result");
|
||||
Assert.AreEqual("Atom10FeedHttpMessageConverterTests.Write", result.Id, "Invalid result");
|
||||
Assert.AreEqual("Test Feed", result.Title.Text, "Invalid result");
|
||||
Assert.AreEqual("This is a test feed", result.Description.Text, "Invalid result");
|
||||
Assert.IsTrue(result.Links.Count == 1, "Invalid result");
|
||||
Assert.AreEqual(new Uri("http://www.springframework.net/Feed"), result.Links[0].Uri, "Invalid result");
|
||||
Assert.AreEqual("Copyright 2010", result.Copyright.Text, "Invalid result");
|
||||
Assert.IsTrue(result.Authors.Count == 1, "Invalid result");
|
||||
Assert.AreEqual("bruno.baia@springframework.net", result.Authors[0].Email, "Invalid result");
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Write()
|
||||
{
|
||||
MemoryStream requestStream = new MemoryStream();
|
||||
|
||||
DateTime now = DateTime.Now;
|
||||
|
||||
string expectedBody = String.Format("<rss xmlns:a10=\"http://www.w3.org/2005/Atom\" version=\"2.0\"><channel><title>Test Feed</title><link>http://www.springframework.net/Feed</link><description>This is a test feed</description><copyright>Copyright 2010</copyright><managingEditor>bruno.baia@springframework.net</managingEditor><lastBuildDate>{0}</lastBuildDate><a10:id>Atom10FeedHttpMessageConverterTests.Write</a10:id></channel></rss>",
|
||||
now.ToString("ddd, dd MMM yyyy HH:mm:ss zzz", CultureInfo.InvariantCulture).Remove(29, 1));
|
||||
|
||||
SyndicationFeed body = new SyndicationFeed("Test Feed", "This is a test feed", new Uri("http://www.springframework.net/Feed"), "Atom10FeedHttpMessageConverterTests.Write", now);
|
||||
SyndicationPerson sp = new SyndicationPerson("bruno.baia@springframework.net", "Bruno Baïa", "http://www.springframework.net/bbaia");
|
||||
body.Authors.Add(sp);
|
||||
body.Copyright = new TextSyndicationContent("Copyright 2010");
|
||||
|
||||
HttpWebRequest webRequest = mocks.CreateMock<HttpWebRequest>();
|
||||
Expect.Call(webRequest.ContentType = "application/rss+xml").PropertyBehavior();
|
||||
Expect.Call(webRequest.ContentLength = 1337).PropertyBehavior();
|
||||
Expect.Call<Stream>(webRequest.GetRequestStream()).Return(requestStream);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
converter.Write(body, null, webRequest);
|
||||
|
||||
byte[] result = requestStream.ToArray();
|
||||
Assert.AreEqual(expectedBody, Encoding.UTF8.GetString(result), "Invalid result");
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,171 @@
|
||||
#if NET_4_0
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Web;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
using Spring.Http.Rest;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Spring.Http.Converters.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// Integration tests for the JsonHttpMessageConverter class.
|
||||
/// </summary>
|
||||
/// <author>Bruno Baia</author>
|
||||
[TestFixture]
|
||||
public class JsonHttpMessageConverterIntegrationTests
|
||||
{
|
||||
#region Logging
|
||||
|
||||
private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(JsonHttpMessageConverterIntegrationTests));
|
||||
|
||||
#endregion
|
||||
|
||||
private WebServiceHost webServiceHost;
|
||||
private string uri = "http://localhost:1337";
|
||||
private RestTemplate template;
|
||||
private MediaType contentType;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
template = new RestTemplate(uri);
|
||||
template.MessageConverters = new List<IHttpMessageConverter>();
|
||||
//template.MessageConverters.Add(new StringHttpMessageConverter()); // for debugging purpose
|
||||
|
||||
contentType = new MediaType("application", "json");
|
||||
|
||||
webServiceHost = new WebServiceHost(typeof(TestService), new Uri(uri));
|
||||
webServiceHost.Open();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDownClass()
|
||||
{
|
||||
webServiceHost.Close();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetForObject()
|
||||
{
|
||||
template.MessageConverters.Add(new JsonHttpMessageConverter());
|
||||
|
||||
User result = template.GetForObject<User>("user/{id}", "1");
|
||||
Assert.IsNotNull(result, "Invalid content");
|
||||
Assert.AreEqual("1", result.ID, "Invalid content");
|
||||
Assert.AreEqual("Bruno Baïa", result.Name, "Invalid content");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostForMessage()
|
||||
{
|
||||
template.MessageConverters.Add(new JsonHttpMessageConverter());
|
||||
|
||||
User user = new User() { Name = "Lisa Baia" };
|
||||
|
||||
HttpResponseMessage result = template.PostForMessage("user", user);
|
||||
Assert.IsNull(result.Body, "Invalid content");
|
||||
Assert.AreEqual(new Uri(new Uri(uri), "/user/3"), new Uri(result.Headers[HttpResponseHeader.Location]), "Invalid location");
|
||||
Assert.AreEqual(HttpStatusCode.Created, result.StatusCode, "Invalid status code");
|
||||
Assert.AreEqual("User id '3' created with 'Lisa Baia'", result.StatusDescription, "Invalid status description");
|
||||
}
|
||||
|
||||
#region REST test service
|
||||
|
||||
[DataContract]
|
||||
public class User
|
||||
{
|
||||
[DataMember]
|
||||
public string ID { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
[ServiceContract]
|
||||
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
|
||||
public class TestService
|
||||
{
|
||||
private IList<User> users;
|
||||
|
||||
public TestService()
|
||||
{
|
||||
users = new List<User>();
|
||||
users.Add(new User() { ID = "1", Name = "Bruno Baïa" });
|
||||
users.Add(new User() { ID = "2", Name = "Marie Baia" });
|
||||
}
|
||||
|
||||
[WebGet(UriTemplate = "user/{id}")]
|
||||
public User GetUser(string id)
|
||||
{
|
||||
WebOperationContext context = WebOperationContext.Current;
|
||||
context.OutgoingResponse.Format = WebMessageFormat.Json;
|
||||
|
||||
foreach (User user in this.users)
|
||||
{
|
||||
if (user.ID.Equals(id, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
context.OutgoingResponse.SetStatusAsNotFound(String.Format("User with id '{0}' not found", id));
|
||||
return null;
|
||||
}
|
||||
|
||||
[WebInvoke(UriTemplate = "user", Method = "POST")]
|
||||
public void Create(User user)
|
||||
{
|
||||
WebOperationContext context = WebOperationContext.Current;
|
||||
context.OutgoingResponse.Format = WebMessageFormat.Json;
|
||||
|
||||
UriTemplateMatch match = context.IncomingRequest.UriTemplateMatch;
|
||||
UriTemplate template = new UriTemplate("/user/{id}");
|
||||
|
||||
MediaType mediaType = MediaType.ParseMediaType(context.IncomingRequest.ContentType);
|
||||
|
||||
if (!String.IsNullOrEmpty(user.ID))
|
||||
{
|
||||
context.OutgoingResponse.StatusCode = HttpStatusCode.BadRequest;
|
||||
context.OutgoingResponse.StatusDescription = String.Format("User id '{0}' already exists", user.ID);
|
||||
return;
|
||||
}
|
||||
|
||||
user.ID = (users.Count + 1).ToString(); // generate new ID
|
||||
|
||||
users.Add(user);
|
||||
|
||||
Uri uri = template.BindByPosition(match.BaseUri, user.ID);
|
||||
context.OutgoingResponse.SetStatusAsCreated(uri);
|
||||
context.OutgoingResponse.StatusDescription = String.Format("User id '{0}' created with '{1}'", user.ID, user.Name);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,125 @@
|
||||
#if NET_3_5
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
using NUnit.Framework;
|
||||
using Rhino.Mocks;
|
||||
|
||||
namespace Spring.Http.Converters.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests for the JsonHttpMessageConverter class.
|
||||
/// </summary>
|
||||
/// <author>Bruno Baia</author>
|
||||
[TestFixture]
|
||||
public class JsonHttpMessageConverterTests
|
||||
{
|
||||
private JsonHttpMessageConverter converter;
|
||||
private MockRepository mocks;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
mocks = new MockRepository();
|
||||
converter = new JsonHttpMessageConverter();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanRead()
|
||||
{
|
||||
Assert.IsTrue(converter.CanRead(typeof(CustomClass), new MediaType("application", "json")));
|
||||
Assert.IsFalse(converter.CanRead(typeof(CustomClass), new MediaType("text", "xml")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanWrite()
|
||||
{
|
||||
Assert.IsTrue(converter.CanRead(typeof(CustomClass), new MediaType("application", "json")));
|
||||
Assert.IsFalse(converter.CanRead(typeof(CustomClass), new MediaType("text", "xml")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Read()
|
||||
{
|
||||
string body = "{\"ID\":\"1\",\"Name\":\"Bruno Baïa\"}";
|
||||
|
||||
HttpWebResponse webResponse = mocks.CreateMock<HttpWebResponse>();
|
||||
Expect.Call<Stream>(webResponse.GetResponseStream()).Return(new MemoryStream(Encoding.UTF8.GetBytes(body)));
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
CustomClass result = converter.Read<CustomClass>(webResponse);
|
||||
Assert.IsNotNull(result, "Invalid result");
|
||||
Assert.AreEqual("1", result.ID, "Invalid result");
|
||||
Assert.AreEqual("Bruno Baïa", result.Name, "Invalid result");
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Write()
|
||||
{
|
||||
MemoryStream requestStream = new MemoryStream();
|
||||
|
||||
string expectedBody = "{\"ID\":\"1\",\"Name\":\"Bruno Baïa\"}";
|
||||
CustomClass body = new CustomClass("1", "Bruno Baïa");
|
||||
|
||||
HttpWebRequest webRequest = mocks.CreateMock<HttpWebRequest>();
|
||||
Expect.Call(webRequest.ContentType = "application/json").PropertyBehavior();
|
||||
Expect.Call(webRequest.ContentLength = 1337).PropertyBehavior();
|
||||
Expect.Call<Stream>(webRequest.GetRequestStream()).Return(requestStream);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
converter.Write(body, null, webRequest);
|
||||
|
||||
byte[] result = requestStream.ToArray();
|
||||
Assert.AreEqual(expectedBody, Encoding.UTF8.GetString(result), "Invalid result");
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
|
||||
#region Test classes
|
||||
|
||||
public class CustomClass
|
||||
{
|
||||
public string ID { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public CustomClass()
|
||||
{
|
||||
}
|
||||
|
||||
public CustomClass(string id, string name)
|
||||
{
|
||||
this.ID = id;
|
||||
this.Name = name;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -50,13 +50,18 @@ namespace Spring.Http.Converters
|
||||
public void CanRead()
|
||||
{
|
||||
Assert.IsTrue(converter.CanRead(typeof(string), new MediaType("text", "plain")));
|
||||
Assert.IsTrue(converter.CanWrite(typeof(string), MediaType.ALL));
|
||||
Assert.IsTrue(converter.CanRead(typeof(string), new MediaType("application", "xml")));
|
||||
Assert.IsFalse(converter.CanRead(typeof(int[]), new MediaType("text", "plain")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanWrite()
|
||||
{
|
||||
Assert.IsTrue(converter.CanWrite(typeof(string), new MediaType("text", "plain")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(string), new MediaType("text", "plain")));
|
||||
Assert.IsTrue(converter.CanWrite(typeof(string), MediaType.ALL));
|
||||
Assert.IsTrue(converter.CanRead(typeof(string), new MediaType("application", "xml")));
|
||||
Assert.IsFalse(converter.CanRead(typeof(int[]), new MediaType("text", "plain")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -65,7 +70,7 @@ namespace Spring.Http.Converters
|
||||
string body = "Hello Bruno Baïa";
|
||||
|
||||
HttpWebResponse webResponse = mocks.CreateMock<HttpWebResponse>();
|
||||
Expect.Call<Stream>(webResponse.GetResponseStream()).Return(new MemoryStream(Encoding.UTF8.GetBytes(body))).Repeat.Once();
|
||||
Expect.Call<Stream>(webResponse.GetResponseStream()).Return(new MemoryStream(Encoding.UTF8.GetBytes(body)));
|
||||
Expect.Call<string>(webResponse.CharacterSet).Return("utf-8").Repeat.Twice();
|
||||
|
||||
mocks.ReplayAll();
|
||||
@@ -79,48 +84,50 @@ namespace Spring.Http.Converters
|
||||
[Test]
|
||||
public void WriteDefaultCharset()
|
||||
{
|
||||
string body = "H\u00e9llo W\u00f6rld";
|
||||
MemoryStream requestStream = new MemoryStream();
|
||||
|
||||
string body = "H\u00e9llo W\u00f6rld";
|
||||
string charSet = "ISO-8859-1";
|
||||
Encoding charSetEncoding = Encoding.GetEncoding(charSet);
|
||||
|
||||
HttpWebRequest webRequest = WebRequest.Create("http://localhost") as HttpWebRequest;
|
||||
webRequest.Method = "POST";
|
||||
HttpWebRequest webRequest = mocks.CreateMock<HttpWebRequest>();
|
||||
Expect.Call(webRequest.ContentType = "text/plain;charset=ISO-8859-1").PropertyBehavior();
|
||||
Expect.Call(webRequest.ContentLength = 1337).PropertyBehavior();
|
||||
Expect.Call<Stream>(webRequest.GetRequestStream()).Return(requestStream);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
converter.Write(body, null, webRequest);
|
||||
|
||||
using (Stream postStream = webRequest.GetRequestStream())
|
||||
{
|
||||
//Assert.AreEqual(body.Length, postStream.Length, "Invalid result");
|
||||
}
|
||||
byte[] result = requestStream.ToArray();
|
||||
Assert.AreEqual(body, charSetEncoding.GetString(result), "Invalid result");
|
||||
|
||||
Assert.AreEqual(new MediaType("text", "plain", charSet), MediaType.ParseMediaType(webRequest.ContentType), "Invalid content-type");
|
||||
Assert.AreEqual(charSetEncoding.GetBytes(body).Length, webRequest.ContentLength, "Invalid content-length");
|
||||
//Assert.IsFalse(String.IsNullOrEmpty(webRequest.Headers[HttpRequestHeader.AcceptCharset]), "Invalid accept-charset");
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WriteUTF8()
|
||||
{
|
||||
string body = "H\u00e9llo W\u00f6rld";
|
||||
MemoryStream requestStream = new MemoryStream();
|
||||
|
||||
string body = "H\u00e9llo W\u00f6rld";
|
||||
string charSet = "UTF-8";
|
||||
Encoding charSetEncoding = Encoding.GetEncoding(charSet);
|
||||
MediaType mediaType = new MediaType("text", "plain", charSet);
|
||||
|
||||
HttpWebRequest webRequest = WebRequest.Create("http://localhost") as HttpWebRequest;
|
||||
webRequest.Method = "POST";
|
||||
HttpWebRequest webRequest = mocks.CreateMock<HttpWebRequest>();
|
||||
Expect.Call(webRequest.ContentType = mediaType.ToString()).PropertyBehavior();
|
||||
Expect.Call(webRequest.ContentLength = 1337).PropertyBehavior();
|
||||
Expect.Call<Stream>(webRequest.GetRequestStream()).Return(requestStream);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
converter.Write(body, mediaType, webRequest);
|
||||
|
||||
using (Stream postStream = webRequest.GetRequestStream())
|
||||
{
|
||||
//Assert.AreEqual(body.Length, postStream.Length, "Invalid result");
|
||||
}
|
||||
byte[] result = requestStream.ToArray();
|
||||
Assert.AreEqual(body, charSetEncoding.GetString(result), "Invalid result");
|
||||
|
||||
Assert.AreEqual(mediaType, MediaType.ParseMediaType(webRequest.ContentType), "Invalid content-type");
|
||||
Assert.AreEqual(charSetEncoding.GetBytes(body).Length, webRequest.ContentLength, "Invalid content-length");
|
||||
//Assert.IsFalse(String.IsNullOrEmpty(webRequest.Headers[HttpRequestHeader.AcceptCharset]), "Invalid accept-charset");
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,328 +0,0 @@
|
||||
#if NET_4_0
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Web;
|
||||
|
||||
using Spring.Http.Converters;
|
||||
using Spring.Http.Converters.Xml;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Spring.Http.Rest.Xml
|
||||
{
|
||||
/// <summary>
|
||||
/// Integration tests for the DataContractHttpMessageConverter class.
|
||||
/// </summary>
|
||||
/// <author>Bruno Baia</author>
|
||||
[TestFixture]
|
||||
public class DataContractHttpMessageConverterIntegrationTests
|
||||
{
|
||||
#region Logging
|
||||
|
||||
private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(RestTemplateIntegrationTests));
|
||||
|
||||
#endregion
|
||||
|
||||
private WebServiceHost webServiceHost;
|
||||
private string uri = "http://localhost:1337";
|
||||
private RestTemplate template;
|
||||
private MediaType contentType;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
template = new RestTemplate(uri);
|
||||
template.MessageConverters = new List<IHttpMessageConverter>();
|
||||
template.MessageConverters.Add(new StringHttpMessageConverter()); // for debugging purpose
|
||||
|
||||
contentType = new MediaType("application", "xml");
|
||||
|
||||
webServiceHost = new WebServiceHost(typeof(TestService), new Uri(uri));
|
||||
webServiceHost.Open();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDownClass()
|
||||
{
|
||||
webServiceHost.Close();
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//public void GetString()
|
||||
//{
|
||||
// string result = template.GetForObject<string>("users");
|
||||
// Assert.AreEqual("2", result, "Invalid content");
|
||||
//}
|
||||
|
||||
[Test]
|
||||
public void GetUser()
|
||||
{
|
||||
template.MessageConverters.Add(new DataContractHttpMessageConverter());
|
||||
|
||||
User result = template.GetForObject<User>("user/{id}", "1");
|
||||
Assert.IsNotNull(result, "Invalid content");
|
||||
Assert.AreEqual("1", result.ID, "Invalid content");
|
||||
Assert.AreEqual("Bruno Baïa", result.Name, "Invalid content");
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//public void GetStringDictionaryTemplateVariables()
|
||||
//{
|
||||
// IDictionary<string, string> uriVariables = new Dictionary<string, string>(1);
|
||||
// uriVariables.Add("id", "2");
|
||||
// string result = template.GetForObject<string>("user/{id}", uriVariables);
|
||||
// Assert.AreEqual("Marie Baia", result, "Invalid content");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//[ExpectedException(typeof(RestClientException),
|
||||
// ExpectedMessage = "The server returned 'User with id '5' not found' with the status code 404 - NotFound.")]
|
||||
//public void GetStringError()
|
||||
//{
|
||||
// string result = template.GetForObject<string>("user/{id}", "5");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void GetStringForMessage()
|
||||
//{
|
||||
// HttpResponseMessage<string> result = template.GetForMessage<string>("user/{id}", "1");
|
||||
// Assert.AreEqual("Bruno Baïa", result.Body, "Invalid content");
|
||||
// Assert.AreEqual(contentType, MediaType.ParseMediaType(result.Headers[HttpResponseHeader.ContentType]), "Invalid content-type");
|
||||
// Assert.AreEqual(HttpStatusCode.OK, result.StatusCode, "Invalid status code");
|
||||
// Assert.AreEqual("OK", result.StatusDescription, "Invalid status description");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//[ExpectedException(typeof(RestClientException),
|
||||
// ExpectedMessage = "Could not extract response: no Content-Type found")]
|
||||
//public void GetStringNoResponse()
|
||||
//{
|
||||
// string result = template.GetForObject<string>("/nothing");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void HeadForHeaders()
|
||||
//{
|
||||
// WebHeaderCollection result = template.HeadForHeaders("head");
|
||||
// Assert.AreEqual(new MediaType("text", "plain"), MediaType.ParseMediaType(result[HttpResponseHeader.ContentType]), "Invalid content-type");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void PostStringForLocation()
|
||||
//{
|
||||
// Uri result = template.PostForLocation("user", "Lisa Baia");
|
||||
// Assert.AreEqual(new Uri(new Uri(uri), "/user/3"), result, "Invalid location");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void PostStringForMessage()
|
||||
//{
|
||||
// HttpResponseMessage<string> result = template.PostForMessage<string>("user", "Lisa Baia");
|
||||
// Assert.AreEqual(new Uri(new Uri(uri), "/user/3"), new Uri(result.Headers[HttpResponseHeader.Location]), "Invalid location");
|
||||
// Assert.AreEqual(HttpStatusCode.Created, result.StatusCode, "Invalid status code");
|
||||
// Assert.AreEqual("User id '3' created with 'Lisa Baia'", result.StatusDescription, "Invalid status description");
|
||||
// Assert.AreEqual("3", result.Body, "Invalid content");
|
||||
//}
|
||||
|
||||
[Test]
|
||||
public void PostStringForObject()
|
||||
{
|
||||
template.MessageConverters.Add(new DataContractHttpMessageConverter());
|
||||
|
||||
User user = new User() { Name = "Lisa Baia" };
|
||||
|
||||
User result = template.PostForObject<User>("user", user);
|
||||
Assert.AreEqual("3", result.ID, "Invalid content");
|
||||
Assert.AreEqual(user.Name, result.Name, "Invalid content");
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//[ExpectedException(typeof(RestClientException),
|
||||
// ExpectedMessage = "The server returned 'Content cannot be null or empty' with the status code 400 - BadRequest.")]
|
||||
//public void PostStringForObjectWithError()
|
||||
//{
|
||||
// string result = template.PostForObject<string>("user", "");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void Put()
|
||||
//{
|
||||
// string result = template.GetForObject<string>("user/1");
|
||||
// Assert.AreEqual("Bruno Baïa", result, "Invalid content");
|
||||
|
||||
// template.Put("user/1", "Bruno Baia");
|
||||
|
||||
// result = template.GetForObject<string>("user/1");
|
||||
// Assert.AreEqual("Bruno Baia", result, "Invalid content");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//[ExpectedException(typeof(RestClientException),
|
||||
// ExpectedMessage = "The server returned 'User id '4' does not exist' with the status code 400 - BadRequest.")]
|
||||
//public void PutWithError()
|
||||
//{
|
||||
// template.Put("user/4", "Dinora Baia");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void Delete()
|
||||
//{
|
||||
// string result = template.GetForObject<string>("users");
|
||||
// Assert.AreEqual("2", result, "Invalid content");
|
||||
|
||||
// template.Delete("user/2");
|
||||
|
||||
// result = template.GetForObject<string>("users");
|
||||
// Assert.AreEqual("1", result, "Invalid content");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//[ExpectedException(typeof(RestClientException),
|
||||
// ExpectedMessage = "The server returned 'User id '10' does not exist' with the status code 400 - BadRequest.")]
|
||||
//public void DeleteWithError()
|
||||
//{
|
||||
// template.Delete("user/10");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void OptionsForAllow()
|
||||
//{
|
||||
// IList<HttpMethod> result = template.OptionsForAllow("allow");
|
||||
// Assert.AreEqual(3, result.Count, "Invalid response");
|
||||
// Assert.IsTrue(result.Contains(HttpMethod.GET), "Invalid response");
|
||||
// Assert.IsTrue(result.Contains(HttpMethod.HEAD), "Invalid response");
|
||||
// Assert.IsTrue(result.Contains(HttpMethod.PUT), "Invalid response");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void ExchangePost()
|
||||
//{
|
||||
// HttpResponseMessage<string> result = template.Exchange<string>(
|
||||
// "user", new HttpRequestMessage("Maryse Baia", HttpMethod.POST));
|
||||
|
||||
// Assert.AreEqual("3", result.Body, "Invalid content");
|
||||
// Assert.AreEqual(HttpStatusCode.Created, result.StatusCode, "Invalid status code");
|
||||
// Assert.AreEqual("User id '3' created with 'Maryse Baia'", result.StatusDescription, "Invalid status description");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void ExchangePut()
|
||||
//{
|
||||
// HttpResponseMessage<string> result = template.Exchange<string>(
|
||||
// "user/1", new HttpRequestMessage("Bruno Baia", HttpMethod.PUT));
|
||||
|
||||
// Assert.AreEqual(HttpStatusCode.OK, result.StatusCode, "Invalid status code");
|
||||
// Assert.AreEqual("User id '1' updated with 'Bruno Baia'", result.StatusDescription, "Invalid status description");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//[ExpectedException(ExpectedMessage = "The server returned 'Not Found' with the status code 404 - NotFound.")]
|
||||
//public void ClientError()
|
||||
//{
|
||||
// template.Execute<object>("clienterror", null, null);
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//[ExpectedException(ExpectedMessage = "The server returned 'Internal Server Error' with the status code 500 - InternalServerError.")]
|
||||
//public void ServerError()
|
||||
//{
|
||||
// template.Execute<object>("servererror", null, null);
|
||||
//}
|
||||
|
||||
#region REST test service
|
||||
|
||||
//[DataContract]
|
||||
public class User
|
||||
{
|
||||
//[DataMember]
|
||||
public string ID { get; set; }
|
||||
|
||||
//[DataMember]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
[ServiceContract]
|
||||
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
|
||||
public class TestService
|
||||
{
|
||||
private IList<User> users;
|
||||
|
||||
public TestService()
|
||||
{
|
||||
users = new List<User>();
|
||||
users.Add(new User() { ID = "1", Name = "Bruno Baïa" });
|
||||
users.Add(new User() { ID = "2", Name = "Marie Baia" });
|
||||
}
|
||||
|
||||
[WebGet(UriTemplate = "user/{id}")]
|
||||
public User GetUser(string id)
|
||||
{
|
||||
WebOperationContext context = WebOperationContext.Current;
|
||||
|
||||
foreach (User user in this.users)
|
||||
{
|
||||
if (user.ID.Equals(id, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
context.OutgoingResponse.SetStatusAsNotFound(String.Format("User with id '{0}' not found", id));
|
||||
return null;
|
||||
}
|
||||
|
||||
[WebInvoke(UriTemplate = "user", Method = "POST")]
|
||||
public User Post(User user)
|
||||
{
|
||||
WebOperationContext context = WebOperationContext.Current;
|
||||
|
||||
UriTemplateMatch match = context.IncomingRequest.UriTemplateMatch;
|
||||
UriTemplate template = new UriTemplate("/user/{id}");
|
||||
|
||||
MediaType mediaType = MediaType.ParseMediaType(context.IncomingRequest.ContentType);
|
||||
|
||||
user.ID = (users.Count + 1).ToString(); // generate new ID
|
||||
|
||||
if (!String.IsNullOrEmpty(user.ID))
|
||||
{
|
||||
context.OutgoingResponse.StatusCode = HttpStatusCode.BadRequest;
|
||||
context.OutgoingResponse.StatusDescription = "Content cannot be null or empty";
|
||||
return user;
|
||||
}
|
||||
|
||||
users.Add(user);
|
||||
|
||||
Uri uri = template.BindByPosition(match.BaseUri, user.ID);
|
||||
context.OutgoingResponse.SetStatusAsCreated(uri);
|
||||
context.OutgoingResponse.StatusDescription = String.Format("User id '{0}' created", user.ID);
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -19,15 +19,14 @@
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using NUnit.Framework;
|
||||
using Rhino.Mocks;
|
||||
using System.Xml;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Spring.Http.Converters.Xml
|
||||
{
|
||||
@@ -51,66 +50,102 @@ namespace Spring.Http.Converters.Xml
|
||||
[Test]
|
||||
public void CanRead()
|
||||
{
|
||||
Assert.IsTrue(converter.CanRead(typeof(CustomClass), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(CustomClass), new MediaType("text", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(CustomClass), new MediaType("application", "soap+xml"))); // application/*+xml
|
||||
Assert.IsTrue(converter.CanRead(typeof(DataContractClass), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(DataContractClass), new MediaType("text", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(DataContractClass), new MediaType("application", "soap+xml"))); // application/*+xml
|
||||
Assert.IsFalse(converter.CanRead(typeof(DataContractClass), new MediaType("text", "plain")));
|
||||
Assert.IsFalse(converter.CanRead(typeof(NonDataContractClass), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(CollectionDataContractClass), new MediaType("application", "xml")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanWrite()
|
||||
{
|
||||
Assert.IsTrue(converter.CanWrite(typeof(CustomClass), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanWrite(typeof(CustomClass), new MediaType("text", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(CustomClass), new MediaType("application", "soap+xml"))); // application/*+xml
|
||||
Assert.IsTrue(converter.CanWrite(typeof(DataContractClass), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanWrite(typeof(DataContractClass), new MediaType("text", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(DataContractClass), new MediaType("application", "soap+xml"))); // application/*+xml
|
||||
Assert.IsFalse(converter.CanRead(typeof(DataContractClass), new MediaType("text", "plain")));
|
||||
Assert.IsFalse(converter.CanRead(typeof(NonDataContractClass), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(CollectionDataContractClass), new MediaType("application", "xml")));
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//public void Read()
|
||||
//{
|
||||
// string body = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><TestElement testAttribute=\"value\" />";
|
||||
[Test]
|
||||
public void Read()
|
||||
{
|
||||
string body = @"<?xml version='1.0' encoding='UTF-8' ?>
|
||||
<DataContractHttpMessageConverterTests.DataContractClass xmlns='http://schemas.datacontract.org/2004/07/Spring.Http.Converters.Xml' xmlns:i='http://www.w3.org/2001/XMLSchema-instance'>
|
||||
<ID>1</ID><Name>Bruno Baïa</Name>
|
||||
</DataContractHttpMessageConverterTests.DataContractClass>";
|
||||
|
||||
// HttpWebResponse webResponse = mocks.CreateMock<HttpWebResponse>();
|
||||
// Expect.Call<Stream>(webResponse.GetResponseStream()).Return(new MemoryStream(Encoding.UTF8.GetBytes(body))).Repeat.Once();
|
||||
HttpWebResponse webResponse = mocks.CreateMock<HttpWebResponse>();
|
||||
Expect.Call<Stream>(webResponse.GetResponseStream()).Return(new MemoryStream(Encoding.UTF8.GetBytes(body)));
|
||||
|
||||
// mocks.ReplayAll();
|
||||
mocks.ReplayAll();
|
||||
|
||||
// XmlDocument result = converter.Read<XmlDocument>(webResponse);
|
||||
// Assert.IsNotNull(result, "Invalid result");
|
||||
DataContractClass result = converter.Read<DataContractClass>(webResponse);
|
||||
Assert.IsNotNull(result, "Invalid result");
|
||||
Assert.AreEqual("1", result.ID, "Invalid result");
|
||||
Assert.AreEqual("Bruno Baïa", result.Name, "Invalid result");
|
||||
|
||||
// mocks.VerifyAll();
|
||||
//}
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//public void Write()
|
||||
//{
|
||||
// XmlDocument body = new XmlDocument();
|
||||
// body.CreateElement("TestElement");
|
||||
[Test]
|
||||
public void Write()
|
||||
{
|
||||
MemoryStream requestStream = new MemoryStream();
|
||||
|
||||
// HttpWebRequest webRequest = WebRequest.Create("http://localhost") as HttpWebRequest;
|
||||
// webRequest.Method = "POST";
|
||||
string expectedBody = "<DataContractHttpMessageConverterTests.DataContractClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://schemas.datacontract.org/2004/07/Spring.Http.Converters.Xml\"><ID>1</ID><Name>Bruno Baïa</Name></DataContractHttpMessageConverterTests.DataContractClass>";
|
||||
DataContractClass body = new DataContractClass("1", "Bruno Baïa");
|
||||
|
||||
// converter.Write(body, null, webRequest);
|
||||
HttpWebRequest webRequest = mocks.CreateMock<HttpWebRequest>();
|
||||
Expect.Call(webRequest.ContentType = "application/xml").PropertyBehavior();
|
||||
Expect.Call(webRequest.ContentLength = 1337).PropertyBehavior();
|
||||
Expect.Call<Stream>(webRequest.GetRequestStream()).Return(requestStream);
|
||||
|
||||
// Assert.AreEqual(new MediaType("application", "xml"), MediaType.ParseMediaType(webRequest.ContentType), "Invalid content-type");
|
||||
mocks.ReplayAll();
|
||||
|
||||
// using (Stream postStream = webRequest.GetRequestStream())
|
||||
// {
|
||||
// using (StreamReader reader = new StreamReader(postStream))
|
||||
// {
|
||||
// string result = reader.ReadToEnd();
|
||||
// Assert.AreEqual(result.Length, webRequest.ContentLength, "Invalid content-length");
|
||||
// }
|
||||
|
||||
// }
|
||||
//}
|
||||
converter.Write(body, null, webRequest);
|
||||
|
||||
requestStream.Position = 0;
|
||||
using (StreamReader reader = new StreamReader(requestStream, Encoding.UTF8))
|
||||
{
|
||||
string result = reader.ReadToEnd();
|
||||
Assert.AreEqual(expectedBody, result, "Invalid result");
|
||||
}
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
|
||||
#region Test classes
|
||||
|
||||
|
||||
[DataContract]
|
||||
public class CustomClass
|
||||
public class DataContractClass
|
||||
{
|
||||
[DataMember]
|
||||
public string ID { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string Name { get; set; }
|
||||
|
||||
public DataContractClass(string id, string name)
|
||||
{
|
||||
this.ID = id;
|
||||
this.Name = name;
|
||||
}
|
||||
}
|
||||
|
||||
[CollectionDataContract]
|
||||
public class CollectionDataContractClass : List<string>
|
||||
{
|
||||
public CollectionDataContractClass()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class NonDataContractClass
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
#if NET_3_5
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
using NUnit.Framework;
|
||||
using Rhino.Mocks;
|
||||
|
||||
namespace Spring.Http.Converters.Xml
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests for the XElementHttpMessageConverter class.
|
||||
/// </summary>
|
||||
/// <author>Bruno Baia</author>
|
||||
[TestFixture]
|
||||
public class XElementHttpMessageConverterTests
|
||||
{
|
||||
private XElementHttpMessageConverter converter;
|
||||
private MockRepository mocks;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
mocks = new MockRepository();
|
||||
converter = new XElementHttpMessageConverter();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanRead()
|
||||
{
|
||||
Assert.IsTrue(converter.CanRead(typeof(XElement), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(XElement), new MediaType("text", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(XElement), new MediaType("application", "soap+xml"))); // application/*+xml
|
||||
Assert.IsFalse(converter.CanRead(typeof(XElement), new MediaType("text", "plain")));
|
||||
Assert.IsFalse(converter.CanRead(typeof(String), new MediaType("application", "xml")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanWrite()
|
||||
{
|
||||
Assert.IsTrue(converter.CanWrite(typeof(XElement), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanWrite(typeof(XElement), new MediaType("text", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(XElement), new MediaType("application", "soap+xml"))); // application/*+xml
|
||||
Assert.IsFalse(converter.CanRead(typeof(XElement), new MediaType("text", "plain")));
|
||||
Assert.IsFalse(converter.CanRead(typeof(String), new MediaType("application", "xml")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Read()
|
||||
{
|
||||
string body = "<?xml version='1.0' encoding='UTF-8' ?><Root><TestElement testAttribute='value'/><TestElement testAttribute='novalue'/></Root>";
|
||||
|
||||
HttpWebResponse webResponse = mocks.CreateMock<HttpWebResponse>();
|
||||
Expect.Call<Stream>(webResponse.GetResponseStream()).Return(new MemoryStream(Encoding.UTF8.GetBytes(body)));
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
XElement result = converter.Read<XElement>(webResponse);
|
||||
Assert.IsNotNull(result, "Invalid result");
|
||||
//XElement xResult = result.Elements()
|
||||
// .Where(x => x.Name == "TestElement" && x.Attribute("testAttribute").Value == "value")
|
||||
// .Single();
|
||||
XElement xResult = (from el in result.Elements()
|
||||
where el.Name == "TestElement" && el.Attribute("testAttribute").Value == "value"
|
||||
select el)
|
||||
.Single();
|
||||
Assert.IsNotNull(xResult, "Invalid result");
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Write()
|
||||
{
|
||||
MemoryStream requestStream = new MemoryStream();
|
||||
|
||||
XElement body = new XElement("Root",
|
||||
new XElement("TestElement", 1),
|
||||
new XElement("TestElement", 2));
|
||||
|
||||
HttpWebRequest webRequest = mocks.CreateMock<HttpWebRequest>();
|
||||
Expect.Call(webRequest.ContentType = "application/xml").PropertyBehavior();
|
||||
Expect.Call(webRequest.ContentLength = 1337).PropertyBehavior();
|
||||
Expect.Call<Stream>(webRequest.GetRequestStream()).Return(requestStream);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
converter.Write(body, null, webRequest);
|
||||
|
||||
requestStream.Position = 0;
|
||||
using (StreamReader reader = new StreamReader(requestStream, Encoding.UTF8))
|
||||
{
|
||||
string result = reader.ReadToEnd();
|
||||
Assert.AreEqual(body.ToString(SaveOptions.DisableFormatting), result, "Invalid result");
|
||||
}
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -22,10 +22,10 @@ using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
|
||||
using NUnit.Framework;
|
||||
using Rhino.Mocks;
|
||||
using System.Xml;
|
||||
|
||||
namespace Spring.Http.Converters.Xml
|
||||
{
|
||||
@@ -52,6 +52,8 @@ namespace Spring.Http.Converters.Xml
|
||||
Assert.IsTrue(converter.CanRead(typeof(XmlDocument), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(XmlDocument), new MediaType("text", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(XmlDocument), new MediaType("application", "soap+xml"))); // application/*+xml
|
||||
Assert.IsFalse(converter.CanRead(typeof(XmlDocument), new MediaType("text", "plain")));
|
||||
Assert.IsFalse(converter.CanRead(typeof(String), new MediaType("application", "xml")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -60,20 +62,27 @@ namespace Spring.Http.Converters.Xml
|
||||
Assert.IsTrue(converter.CanWrite(typeof(XmlDocument), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanWrite(typeof(XmlDocument), new MediaType("text", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(XmlDocument), new MediaType("application", "soap+xml"))); // application/*+xml
|
||||
Assert.IsFalse(converter.CanRead(typeof(XmlDocument), new MediaType("text", "plain")));
|
||||
Assert.IsFalse(converter.CanRead(typeof(String), new MediaType("application", "xml")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Read()
|
||||
{
|
||||
string body = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><TestElement testAttribute=\"value\" />";
|
||||
string body = "<?xml version='1.0' encoding='UTF-8' ?><TestElement testAttribute='value' />";
|
||||
|
||||
HttpWebResponse webResponse = mocks.CreateMock<HttpWebResponse>();
|
||||
Expect.Call<Stream>(webResponse.GetResponseStream()).Return(new MemoryStream(Encoding.UTF8.GetBytes(body))).Repeat.Once();
|
||||
Expect.Call<Stream>(webResponse.GetResponseStream()).Return(new MemoryStream(Encoding.UTF8.GetBytes(body)));
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
XmlDocument result = converter.Read<XmlDocument>(webResponse);
|
||||
Assert.IsNotNull(result, "Invalid result");
|
||||
XmlNode xmlNodeResult = result.SelectSingleNode("//TestElement");
|
||||
Assert.IsNotNull(xmlNodeResult, "Invalid result");
|
||||
Assert.AreEqual("TestElement", xmlNodeResult.LocalName, "Invalid result");
|
||||
Assert.IsNotNull(xmlNodeResult.Attributes["testAttribute"], "Invalid result");
|
||||
Assert.AreEqual("value", xmlNodeResult.Attributes["testAttribute"].Value, "Invalid result");
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
@@ -81,25 +90,28 @@ namespace Spring.Http.Converters.Xml
|
||||
[Test]
|
||||
public void Write()
|
||||
{
|
||||
XmlDocument body = new XmlDocument();
|
||||
body.CreateElement("TestElement");
|
||||
MemoryStream requestStream = new MemoryStream();
|
||||
|
||||
HttpWebRequest webRequest = WebRequest.Create("http://localhost") as HttpWebRequest;
|
||||
webRequest.Method = "POST";
|
||||
XmlDocument body = new XmlDocument();
|
||||
body.LoadXml("<?xml version='1.0' encoding='UTF-8' ?><TestElement testAttribute='value' />");
|
||||
|
||||
HttpWebRequest webRequest = mocks.CreateMock<HttpWebRequest>();
|
||||
Expect.Call(webRequest.ContentType = "application/xml").PropertyBehavior();
|
||||
Expect.Call(webRequest.ContentLength = 1337).PropertyBehavior();
|
||||
Expect.Call<Stream>(webRequest.GetRequestStream()).Return(requestStream);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
converter.Write(body, null, webRequest);
|
||||
|
||||
Assert.AreEqual(new MediaType("application", "xml"), MediaType.ParseMediaType(webRequest.ContentType), "Invalid content-type");
|
||||
|
||||
using (Stream postStream = webRequest.GetRequestStream())
|
||||
requestStream.Position = 0;
|
||||
using (StreamReader reader = new StreamReader(requestStream, Encoding.UTF8))
|
||||
{
|
||||
using (StreamReader reader = new StreamReader(postStream))
|
||||
{
|
||||
string result = reader.ReadToEnd();
|
||||
Assert.AreEqual(result.Length, webRequest.ContentLength, "Invalid content-length");
|
||||
}
|
||||
|
||||
string result = reader.ReadToEnd();
|
||||
Assert.AreEqual(body.OuterXml, result, "Invalid result");
|
||||
}
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,240 @@
|
||||
#if NET_4_0
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Xml.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Web;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
using Spring.Http.Rest;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Spring.Http.Converters.Xml
|
||||
{
|
||||
/// <summary>
|
||||
/// Integration tests for the Xml based IHttpMessageConverter class.
|
||||
/// </summary>
|
||||
/// <author>Bruno Baia</author>
|
||||
[TestFixture]
|
||||
public class XmlHttpMessageConverterIntegrationTests
|
||||
{
|
||||
#region Logging
|
||||
|
||||
private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(XmlHttpMessageConverterIntegrationTests));
|
||||
|
||||
#endregion
|
||||
|
||||
private WebServiceHost webServiceHost;
|
||||
private string uri = "http://localhost:1337";
|
||||
private RestTemplate template;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
template = new RestTemplate(uri);
|
||||
template.MessageConverters = new List<IHttpMessageConverter>();
|
||||
//template.MessageConverters.Add(new StringHttpMessageConverter()); // for debugging purpose
|
||||
|
||||
webServiceHost = new WebServiceHost(typeof(TestService), new Uri(uri));
|
||||
webServiceHost.Open();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDownClass()
|
||||
{
|
||||
webServiceHost.Close();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DataContractGetForObject()
|
||||
{
|
||||
template.MessageConverters.Add(new DataContractHttpMessageConverter());
|
||||
|
||||
User result = template.GetForObject<User>("user/dc/{id}", "1");
|
||||
Assert.IsNotNull(result, "Invalid content");
|
||||
Assert.AreEqual("1", result.ID, "Invalid content");
|
||||
Assert.AreEqual("Bruno Baïa", result.Name, "Invalid content");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DataContractPostForMessage()
|
||||
{
|
||||
template.MessageConverters.Add(new DataContractHttpMessageConverter());
|
||||
|
||||
User user = new User() { Name = "Lisa Baia" };
|
||||
|
||||
HttpResponseMessage result = template.PostForMessage("user/dc", user);
|
||||
Assert.IsNull(result.Body, "Invalid content");
|
||||
Assert.AreEqual(new Uri(new Uri(uri), "/user/dc/3"), new Uri(result.Headers[HttpResponseHeader.Location]), "Invalid location");
|
||||
Assert.AreEqual(HttpStatusCode.Created, result.StatusCode, "Invalid status code");
|
||||
Assert.AreEqual("User id '3' created with 'Lisa Baia'", result.StatusDescription, "Invalid status description");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void XElementGetForObject()
|
||||
{
|
||||
template.MessageConverters.Add(new XElementHttpMessageConverter());
|
||||
|
||||
XElement result = template.GetForObject<XElement>("user/xml/{id}", "1");
|
||||
Assert.IsNotNull(result, "Invalid content");
|
||||
Assert.AreEqual("1", result.Element("ID").Value, "Invalid content");
|
||||
Assert.AreEqual("Bruno Baïa", result.Element("Name").Value, "Invalid content");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void XElementPostForMessage()
|
||||
{
|
||||
template.MessageConverters.Add(new XElementHttpMessageConverter());
|
||||
|
||||
XElement user = new XElement("User",
|
||||
new XElement("Name", "Lisa Baia"));
|
||||
|
||||
HttpResponseMessage result = template.PostForMessage("user/xml", user);
|
||||
Assert.IsNull(result.Body, "Invalid content");
|
||||
Assert.AreEqual(new Uri(new Uri(uri), "/user/xml/3"), new Uri(result.Headers[HttpResponseHeader.Location]), "Invalid location");
|
||||
Assert.AreEqual(HttpStatusCode.Created, result.StatusCode, "Invalid status code");
|
||||
Assert.AreEqual("User id '3' created with 'Lisa Baia'", result.StatusDescription, "Invalid status description");
|
||||
}
|
||||
|
||||
#region REST test service
|
||||
|
||||
[DataContract]
|
||||
public class User
|
||||
{
|
||||
[DataMember]
|
||||
public string ID { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
[ServiceContract]
|
||||
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
|
||||
public class TestService
|
||||
{
|
||||
private IList<User> users;
|
||||
|
||||
public TestService()
|
||||
{
|
||||
users = new List<User>();
|
||||
users.Add(new User() { ID = "1", Name = "Bruno Baïa" });
|
||||
users.Add(new User() { ID = "2", Name = "Marie Baia" });
|
||||
}
|
||||
|
||||
[WebGet(UriTemplate = "user/dc/{id}")]
|
||||
public User GetUserDataContract(string id)
|
||||
{
|
||||
WebOperationContext context = WebOperationContext.Current;
|
||||
|
||||
foreach (User user in this.users)
|
||||
{
|
||||
if (user.ID.Equals(id, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
context.OutgoingResponse.SetStatusAsNotFound(String.Format("User with id '{0}' not found", id));
|
||||
return null;
|
||||
}
|
||||
|
||||
[WebInvoke(UriTemplate = "user/dc", Method = "POST")]
|
||||
public void CreateDataContract(User user)
|
||||
{
|
||||
WebOperationContext context = WebOperationContext.Current;
|
||||
|
||||
UriTemplateMatch match = context.IncomingRequest.UriTemplateMatch;
|
||||
UriTemplate template = new UriTemplate("/user/dc/{id}");
|
||||
|
||||
MediaType mediaType = MediaType.ParseMediaType(context.IncomingRequest.ContentType);
|
||||
|
||||
if (!String.IsNullOrEmpty(user.ID))
|
||||
{
|
||||
context.OutgoingResponse.StatusCode = HttpStatusCode.BadRequest;
|
||||
context.OutgoingResponse.StatusDescription = String.Format("User id '{0}' already exists", user.ID);
|
||||
return;
|
||||
}
|
||||
|
||||
user.ID = (users.Count + 1).ToString(); // generate new ID
|
||||
|
||||
users.Add(user);
|
||||
|
||||
Uri uri = template.BindByPosition(match.BaseUri, user.ID);
|
||||
context.OutgoingResponse.SetStatusAsCreated(uri);
|
||||
context.OutgoingResponse.StatusDescription = String.Format("User id '{0}' created with '{1}'", user.ID, user.Name);
|
||||
}
|
||||
|
||||
[WebGet(UriTemplate = "user/xml/{id}")]
|
||||
public XElement GetUserXElement(string id)
|
||||
{
|
||||
WebOperationContext context = WebOperationContext.Current;
|
||||
|
||||
foreach (User user in this.users)
|
||||
{
|
||||
if (user.ID.Equals(id, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return new XElement("User",
|
||||
new XElement("ID", user.ID),
|
||||
new XElement("Name", user.Name));
|
||||
}
|
||||
}
|
||||
|
||||
context.OutgoingResponse.SetStatusAsNotFound(String.Format("User with id '{0}' not found", id));
|
||||
return null;
|
||||
}
|
||||
|
||||
[WebInvoke(UriTemplate = "user/xml", Method = "POST")]
|
||||
public void CreateXElement(XElement user)
|
||||
{
|
||||
WebOperationContext context = WebOperationContext.Current;
|
||||
|
||||
UriTemplateMatch match = context.IncomingRequest.UriTemplateMatch;
|
||||
UriTemplate template = new UriTemplate("/user/xml/{id}");
|
||||
|
||||
MediaType mediaType = MediaType.ParseMediaType(context.IncomingRequest.ContentType);
|
||||
|
||||
if (user.Element("ID") != null && !String.IsNullOrEmpty(user.Element("ID").Value))
|
||||
{
|
||||
context.OutgoingResponse.StatusCode = HttpStatusCode.BadRequest;
|
||||
context.OutgoingResponse.StatusDescription = String.Format("User id '{0}' already exists", user.Element("ID"));
|
||||
return;
|
||||
}
|
||||
|
||||
User newUser = new User();
|
||||
newUser.ID = (users.Count + 1).ToString(); // generate new ID
|
||||
newUser.Name = user.Element("Name").Value;
|
||||
|
||||
users.Add(newUser);
|
||||
|
||||
Uri uri = template.BindByPosition(match.BaseUri, newUser.ID);
|
||||
context.OutgoingResponse.SetStatusAsCreated(uri);
|
||||
context.OutgoingResponse.StatusDescription = String.Format("User id '{0}' created with '{1}'", newUser.ID, newUser.Name);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,137 @@
|
||||
#if NET_3_0
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
using NUnit.Framework;
|
||||
using Rhino.Mocks;
|
||||
|
||||
namespace Spring.Http.Converters.Xml
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests for the XmlSerializableHttpMessageConverter class.
|
||||
/// </summary>
|
||||
/// <author>Bruno Baia</author>
|
||||
[TestFixture]
|
||||
public class XmlSerializableHttpMessageConverterTests
|
||||
{
|
||||
private XmlSerializableHttpMessageConverter converter;
|
||||
private MockRepository mocks;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
mocks = new MockRepository();
|
||||
converter = new XmlSerializableHttpMessageConverter();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanRead()
|
||||
{
|
||||
Assert.IsTrue(converter.CanRead(typeof(CustomClass), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(CustomClass), new MediaType("text", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(CustomClass), new MediaType("application", "soap+xml"))); // application/*+xml
|
||||
Assert.IsFalse(converter.CanRead(typeof(CustomClass), new MediaType("text", "plain")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanWrite()
|
||||
{
|
||||
Assert.IsTrue(converter.CanRead(typeof(CustomClass), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(CustomClass), new MediaType("text", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(CustomClass), new MediaType("application", "soap+xml"))); // application/*+xml
|
||||
Assert.IsFalse(converter.CanRead(typeof(CustomClass), new MediaType("text", "plain")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Read()
|
||||
{
|
||||
string body = @"<?xml version='1.0' encoding='utf-8'?>
|
||||
<CustomClass xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
|
||||
<ID>1</ID>
|
||||
<Name>Bruno Baïa</Name>
|
||||
</CustomClass>";
|
||||
|
||||
HttpWebResponse webResponse = mocks.CreateMock<HttpWebResponse>();
|
||||
Expect.Call<Stream>(webResponse.GetResponseStream()).Return(new MemoryStream(Encoding.UTF8.GetBytes(body)));
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
CustomClass result = converter.Read<CustomClass>(webResponse);
|
||||
Assert.IsNotNull(result, "Invalid result");
|
||||
Assert.AreEqual("1", result.ID, "Invalid result");
|
||||
Assert.AreEqual("Bruno Baïa", result.Name, "Invalid result");
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Write()
|
||||
{
|
||||
MemoryStream requestStream = new MemoryStream();
|
||||
|
||||
string expectedBody = "<?xml version=\"1.0\" encoding=\"utf-8\"?><CustomClass xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><ID>1</ID><Name>Bruno Baïa</Name></CustomClass>";
|
||||
CustomClass body = new CustomClass("1", "Bruno Baïa");
|
||||
|
||||
HttpWebRequest webRequest = mocks.CreateMock<HttpWebRequest>();
|
||||
Expect.Call(webRequest.ContentType = "application/xml").PropertyBehavior();
|
||||
Expect.Call(webRequest.ContentLength = 1337).PropertyBehavior();
|
||||
Expect.Call<Stream>(webRequest.GetRequestStream()).Return(requestStream);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
converter.Write(body, null, webRequest);
|
||||
|
||||
requestStream.Position = 0;
|
||||
using (StreamReader reader = new StreamReader(requestStream, Encoding.UTF8))
|
||||
{
|
||||
string result = reader.ReadToEnd();
|
||||
Assert.AreEqual(expectedBody, result, "Invalid result");
|
||||
}
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
|
||||
#region Test classes
|
||||
|
||||
public class CustomClass
|
||||
{
|
||||
public string ID { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public CustomClass()
|
||||
{
|
||||
}
|
||||
|
||||
public CustomClass(string id, string name)
|
||||
{
|
||||
this.ID = id;
|
||||
this.Name = name;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -222,7 +222,7 @@ namespace Spring.Http.Rest
|
||||
[Test]
|
||||
public void ExchangePut()
|
||||
{
|
||||
HttpResponseMessage<string> result = template.Exchange<string>(
|
||||
HttpResponseMessage result = template.Exchange(
|
||||
"user/1", new HttpRequestMessage("Bruno Baia", HttpMethod.PUT));
|
||||
|
||||
Assert.AreEqual(HttpStatusCode.OK, result.StatusCode, "Invalid status code");
|
||||
@@ -458,7 +458,6 @@ namespace Spring.Http.Rest
|
||||
|
||||
context.OutgoingResponse.StatusCode = HttpStatusCode.OK;
|
||||
context.OutgoingResponse.StatusDescription = String.Format("User id '{0}' updated with '{1}'", id, name);
|
||||
//context.OutgoingResponse.ContentType = "text/plain";
|
||||
}
|
||||
|
||||
[WebInvoke(UriTemplate = "user/{id}", Method = "DELETE")]
|
||||
|
||||
@@ -158,6 +158,7 @@ namespace Spring.Http.Rest
|
||||
Expect.Call<WebHeaderCollection>(request.Headers).Return(requestHeaders).Repeat.Any();
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
//Expect.Call<string>(response.ContentType).Return(textPlain.ToString()).Repeat.AtLeastOnce();
|
||||
WebHeaderCollection responseHeaders = new WebHeaderCollection();
|
||||
responseHeaders[HttpResponseHeader.ContentType] = textPlain.ToString();
|
||||
Expect.Call<WebHeaderCollection>(response.Headers).Return(responseHeaders).Repeat.Any();
|
||||
@@ -181,7 +182,7 @@ namespace Spring.Http.Rest
|
||||
IList<MediaType> mediaTypes = new List<MediaType>(1);
|
||||
mediaTypes.Add(textPlain);
|
||||
Expect.Call<IList<MediaType>>(converter.SupportedMediaTypes).Return(mediaTypes);
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com/resource"))).Return(request);
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com/resource"))).Return(request);
|
||||
Expect.Call(request.Method = "GET");
|
||||
Expect.Call(request.Accept = "foo/bar");
|
||||
WebHeaderCollection requestHeaders = new WebHeaderCollection();
|
||||
@@ -279,6 +280,7 @@ namespace Spring.Http.Rest
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
Expect.Call(request.Method = "POST");
|
||||
MediaType contentType = new MediaType("text", "plain");
|
||||
Expect.Call(request.ContentType = contentType.ToString());
|
||||
Expect.Call<bool>(converter.CanWrite(typeof(string), contentType)).Return(true);
|
||||
WebHeaderCollection requestHeaders = new WebHeaderCollection();
|
||||
Expect.Call<WebHeaderCollection>(request.Headers).Return(requestHeaders).Repeat.Any();
|
||||
@@ -301,7 +303,7 @@ namespace Spring.Http.Rest
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostForLocationEntityCustomHeader()
|
||||
public void PostForLocationMessageCustomHeader()
|
||||
{
|
||||
string helloWorld = "Hello World";
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
@@ -399,7 +401,7 @@ namespace Spring.Http.Rest
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostForEntity()
|
||||
public void PostForMessage()
|
||||
{
|
||||
Expect.Call<bool>(converter.CanRead(typeof(Version), null)).Return(true);
|
||||
MediaType textPlain = new MediaType("text", "plain");
|
||||
@@ -434,6 +436,31 @@ namespace Spring.Http.Rest
|
||||
Assert.AreEqual("OK", result.StatusDescription, "Invalid status description");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostForMessageNoBody()
|
||||
{
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
Expect.Call(request.Method = "POST");
|
||||
WebHeaderCollection requestHeaders = new WebHeaderCollection();
|
||||
Expect.Call<WebHeaderCollection>(request.Headers).Return(requestHeaders).Repeat.Any();
|
||||
string helloWorld = "Hello World";
|
||||
Expect.Call<bool>(converter.CanWrite(typeof(string), null)).Return(true);
|
||||
converter.Write(helloWorld, null, request);
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
WebHeaderCollection responseHeaders = new WebHeaderCollection();
|
||||
Expect.Call<WebHeaderCollection>(response.Headers).Return(responseHeaders);
|
||||
Expect.Call<HttpStatusCode>(response.StatusCode).Return(HttpStatusCode.Created);
|
||||
Expect.Call<string>(response.StatusDescription).Return("CREATED");
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
HttpResponseMessage result = template.PostForMessage("http://example.com", helloWorld);
|
||||
Assert.IsNull(result.Body, "Invalid POST result");
|
||||
Assert.AreEqual(HttpStatusCode.Created, result.StatusCode, "Invalid status code");
|
||||
Assert.AreEqual("CREATED", result.StatusDescription, "Invalid status description");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostForObjectNull()
|
||||
{
|
||||
|
||||
@@ -87,28 +87,43 @@
|
||||
<Reference Include="System">
|
||||
<Name>System</Name>
|
||||
</Reference>
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.Serialization">
|
||||
<RequiredTargetFramework>3.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.ServiceModel">
|
||||
<RequiredTargetFramework>3.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.ServiceModel.Web">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.XML" />
|
||||
<Reference Include="System.Xml.Linq">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Http\Converters\ByteArrayHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\Feed\Atom10FeedHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\Feed\FeedHttpMessageConverterIntegrationTests.cs" />
|
||||
<Compile Include="Http\Converters\Feed\Rss20FeedHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\Json\JsonHttpMessageConverterIntegrationTests.cs" />
|
||||
<Compile Include="Http\Converters\Json\JsonHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\StringHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\Xml\DataContractHttpMessageConverterIntegrationTests.cs" />
|
||||
<Compile Include="Http\Converters\Xml\DataContractHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\Xml\XElementHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\Xml\XmlDocumentHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\Xml\XmlHttpMessageConverterIntegrationTests.cs" />
|
||||
<Compile Include="Http\Converters\Xml\XmlSerializableHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\MediaTypeTests.cs" />
|
||||
<Compile Include="Http\Rest\RestTemplateIntegrationTests.cs" />
|
||||
<Compile Include="Util\UriTemplateTests.cs" />
|
||||
<Compile Include="Http\Rest\RestTemplateTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Core\Spring.Core.2008.csproj">
|
||||
<Project>{710961A3-0DF4-49E4-A26E-F5B9C044AC84}</Project>
|
||||
<Name>Spring.Core.2008</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Http\Spring.Http.2008.csproj">
|
||||
<Project>{FAC04F79-4B1F-1D13-B30F-00EE04EC0FBC}</Project>
|
||||
<Name>Spring.Http.2008</Name>
|
||||
|
||||
@@ -108,19 +108,30 @@
|
||||
<Reference Include="System">
|
||||
<Name>System</Name>
|
||||
</Reference>
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.ServiceModel.Web" />
|
||||
<Reference Include="System.XML" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Http\Converters\ByteArrayHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\Feed\Atom10FeedHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\Feed\FeedHttpMessageConverterIntegrationTests.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Http\Converters\Feed\Rss20FeedHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\Json\JsonHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\Json\JsonHttpMessageConverterIntegrationTests.cs" />
|
||||
<Compile Include="Http\Converters\StringHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\Xml\XmlHttpMessageConverterIntegrationTests.cs" />
|
||||
<Compile Include="Http\Converters\Xml\XElementHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\Xml\XmlSerializableHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\Xml\DataContractHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\Xml\DataContractHttpMessageConverterIntegrationTests.cs" />
|
||||
<Compile Include="Http\Converters\Xml\XmlDocumentHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\MediaTypeTests.cs" />
|
||||
<Compile Include="Http\Rest\RestTemplateIntegrationTests.cs" />
|
||||
@@ -128,10 +139,6 @@
|
||||
<Compile Include="Util\UriTemplateTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Core\Spring.Core.2010.csproj">
|
||||
<Project>{710961A3-0DF4-49E4-A26E-F5B9C044AC84}</Project>
|
||||
<Name>Spring.Core.2010</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Http\Spring.Http.2010.csproj">
|
||||
<Project>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</Project>
|
||||
<Name>Spring.Http.2010</Name>
|
||||
|
||||
Reference in New Issue
Block a user