1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //------------------------------------------------------------
4 #pragma warning disable 1634, 1691
6 namespace System.ServiceModel.Web
9 using System.Diagnostics.CodeAnalysis;
12 using System.Runtime.Serialization.Json;
13 using System.ServiceModel;
14 using System.ServiceModel.Channels;
15 using System.ServiceModel.Description;
16 using System.ServiceModel.Syndication;
19 using System.Xml.Linq;
20 using System.Xml.Serialization;
21 using System.ServiceModel.Dispatcher;
23 public class WebOperationContext : IExtension<OperationContext>
25 internal static readonly string DefaultTextMediaType = "text/plain";
26 internal static readonly string DefaultJsonMediaType = JsonGlobals.applicationJsonMediaType;
27 internal static readonly string DefaultXmlMediaType = "application/xml";
28 internal static readonly string DefaultAtomMediaType = "application/atom+xml";
29 internal static readonly string DefaultStreamMediaType = WebHttpBehavior.defaultStreamContentType;
31 OperationContext operationContext;
33 public WebOperationContext(OperationContext operationContext)
35 if (operationContext == null)
37 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("operationContext");
39 this.operationContext = operationContext;
40 #pragma warning disable 56506 // Microsoft, operationContext.Extensions is never null
41 if (operationContext.Extensions.Find<WebOperationContext>() == null)
43 operationContext.Extensions.Add(this);
45 #pragma warning enable 56506
48 public static WebOperationContext Current
52 if (OperationContext.Current == null)
56 WebOperationContext existing = OperationContext.Current.Extensions.Find<WebOperationContext>();
61 return new WebOperationContext(OperationContext.Current);
65 public IncomingWebRequestContext IncomingRequest
67 get { return new IncomingWebRequestContext(this.operationContext); }
70 public IncomingWebResponseContext IncomingResponse
72 get { return new IncomingWebResponseContext(this.operationContext); }
75 public OutgoingWebRequestContext OutgoingRequest
77 get { return new OutgoingWebRequestContext(this.operationContext); }
80 public OutgoingWebResponseContext OutgoingResponse
82 get { return new OutgoingWebResponseContext(this.operationContext); }
85 public void Attach(OperationContext owner)
89 public void Detach(OperationContext owner)
93 public Message CreateJsonResponse<T>(T instance)
95 DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
96 return CreateJsonResponse<T>(instance, serializer);
99 [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "CreateJsonMessage requires the DataContractJsonSerializer. Allowing the base type XmlObjectSerializer would let deveopers supply a non-Json Serializer.")]
100 public Message CreateJsonResponse<T>(T instance, DataContractJsonSerializer serializer)
102 if (serializer == null)
104 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serializer");
106 Message message = Message.CreateMessage(MessageVersion.None, (string)null, instance, serializer);
107 message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.JsonProperty);
108 AddContentType(WebOperationContext.DefaultJsonMediaType, this.OutgoingResponse.BindingWriteEncoding);
112 public Message CreateXmlResponse<T>(T instance)
114 System.Runtime.Serialization.DataContractSerializer serializer = new System.Runtime.Serialization.DataContractSerializer(typeof(T));
115 return CreateXmlResponse(instance, serializer);
118 public Message CreateXmlResponse<T>(T instance, System.Runtime.Serialization.XmlObjectSerializer serializer)
120 if (serializer == null)
122 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serializer");
124 Message message = Message.CreateMessage(MessageVersion.None, (string)null, instance, serializer);
125 message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.XmlProperty);
126 AddContentType(WebOperationContext.DefaultXmlMediaType, this.OutgoingResponse.BindingWriteEncoding);
130 public Message CreateXmlResponse<T>(T instance, XmlSerializer serializer)
132 if (serializer == null)
134 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serializer");
136 Message message = Message.CreateMessage(MessageVersion.None, (string)null, new XmlSerializerBodyWriter(instance, serializer));
137 message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.XmlProperty);
138 AddContentType(WebOperationContext.DefaultXmlMediaType, this.OutgoingResponse.BindingWriteEncoding);
142 [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "Other XNode derived types such as XAttribute don't make sense in this context, so we are not using the XNode base type.")]
143 public Message CreateXmlResponse(XDocument document)
145 if (document == null)
147 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("document");
150 if (document.FirstNode == null)
152 message = Message.CreateMessage(MessageVersion.None, (string)null);
156 message = Message.CreateMessage(MessageVersion.None, (string)null, document.CreateReader());
158 message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.XmlProperty);
159 AddContentType(WebOperationContext.DefaultXmlMediaType, this.OutgoingResponse.BindingWriteEncoding);
163 [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "Other XNode derived types such as XAttribute don't make sense in this context, so we are not using the XNode base type.")]
164 public Message CreateXmlResponse(XElement element)
168 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element");
170 Message message = Message.CreateMessage(MessageVersion.None, (string)null, element.CreateReader());
171 message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.XmlProperty);
172 AddContentType(WebOperationContext.DefaultXmlMediaType, this.OutgoingResponse.BindingWriteEncoding);
176 public Message CreateAtom10Response(SyndicationItem item)
180 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("item");
182 Message message = Message.CreateMessage(MessageVersion.None, (string)null, item.GetAtom10Formatter());
183 message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.XmlProperty);
184 AddContentType(WebOperationContext.DefaultAtomMediaType, this.OutgoingResponse.BindingWriteEncoding);
188 public Message CreateAtom10Response(SyndicationFeed feed)
192 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("feed");
194 Message message = Message.CreateMessage(MessageVersion.None, (string)null, feed.GetAtom10Formatter());
195 message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.XmlProperty);
196 AddContentType(WebOperationContext.DefaultAtomMediaType, this.OutgoingResponse.BindingWriteEncoding);
200 public Message CreateAtom10Response(ServiceDocument document)
202 if (document == null)
204 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("document");
206 Message message = Message.CreateMessage(MessageVersion.None, (string)null, document.GetFormatter());
207 message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.XmlProperty);
208 AddContentType(WebOperationContext.DefaultAtomMediaType, this.OutgoingResponse.BindingWriteEncoding);
212 public Message CreateTextResponse(string text)
214 return CreateTextResponse(text, WebOperationContext.DefaultTextMediaType, Encoding.UTF8);
217 public Message CreateTextResponse(string text, string contentType)
219 return CreateTextResponse(text, contentType, Encoding.UTF8);
222 public Message CreateTextResponse(string text, string contentType, Encoding encoding)
226 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("text");
228 if (contentType == null)
230 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contentType");
232 if (encoding == null)
234 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("encoding");
237 Message message = new HttpStreamMessage(StreamBodyWriter.CreateStreamBodyWriter((stream) =>
239 byte[] preamble = encoding.GetPreamble();
240 if (preamble.Length > 0)
242 stream.Write(preamble, 0, preamble.Length);
244 byte[] bytes = encoding.GetBytes(text);
245 stream.Write(bytes, 0, bytes.Length);
248 message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.RawProperty);
249 AddContentType(contentType, null);
253 public Message CreateTextResponse(Action<TextWriter> textWriter, string contentType)
255 Encoding encoding = this.OutgoingResponse.BindingWriteEncoding;
256 if (encoding == null)
258 encoding = Encoding.UTF8;
260 return CreateTextResponse(textWriter, contentType, encoding);
263 public Message CreateTextResponse(Action<TextWriter> textWriter, string contentType, Encoding encoding)
265 if (textWriter == null)
267 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("textWriter");
269 if (contentType == null)
271 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contentType");
273 if (encoding == null)
275 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("encoding");
278 Message message = new HttpStreamMessage(StreamBodyWriter.CreateStreamBodyWriter((stream) =>
280 using (TextWriter writer = new StreamWriter(stream, encoding))
285 message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.RawProperty);
286 AddContentType(contentType, null);
290 public Message CreateStreamResponse(Stream stream, string contentType)
294 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("stream");
296 if (contentType == null)
298 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contentType");
300 Message message = ByteStreamMessage.CreateMessage(stream);
301 message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.RawProperty);
302 AddContentType(contentType, null);
306 [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "Using the StreamBodyWriter type instead of the BodyWriter type for discoverability. The StreamBodyWriter provides a helpful overload of the OnWriteBodyContents method that takes a Stream")]
307 public Message CreateStreamResponse(StreamBodyWriter bodyWriter, string contentType)
309 if (bodyWriter == null)
311 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("bodyWriter");
313 if (contentType == null)
315 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contentType");
317 Message message = new HttpStreamMessage(bodyWriter);
318 message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.RawProperty);
319 AddContentType(contentType, null);
323 public Message CreateStreamResponse(Action<Stream> streamWriter, string contentType)
325 if (streamWriter == null)
327 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("streamWriter");
329 if (contentType == null)
331 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contentType");
333 Message message = new HttpStreamMessage(StreamBodyWriter.CreateStreamBodyWriter(streamWriter));
334 message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.RawProperty);
335 AddContentType(contentType, null);
339 public UriTemplate GetUriTemplate(string operationName)
341 if (String.IsNullOrEmpty(operationName))
343 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("operationName");
346 WebHttpDispatchOperationSelector selector = OperationContext.Current.EndpointDispatcher.DispatchRuntime.OperationSelector as WebHttpDispatchOperationSelector;
347 if (selector == null)
349 throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR2.GetString(SR2.OperationSelectorNotWebSelector, typeof(WebHttpDispatchOperationSelector))));
351 return selector.GetUriTemplate(operationName);
354 void AddContentType(string contentType, Encoding encoding)
356 if (string.IsNullOrEmpty(this.OutgoingResponse.ContentType))
358 if (encoding != null)
360 contentType = WebMessageEncoderFactory.GetContentType(contentType, encoding);
362 this.OutgoingResponse.ContentType = contentType;
366 class XmlSerializerBodyWriter : BodyWriter
369 XmlSerializer serializer;
371 public XmlSerializerBodyWriter(object instance, XmlSerializer serializer)
374 if (instance == null)
376 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("instance");
378 if (serializer == null)
380 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serializer");
382 this.instance = instance;
383 this.serializer = serializer;
386 protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
388 serializer.Serialize(writer, instance);