Renamed Channel.Send method to Channel.PrepareResponse and then added a new Send...
[dotnetoauth.git] / src / DotNetOpenAuth / OpenId / Provider / Request.cs
blob6546e38e1f16ecfca69ddd5de56e1208c76b6d2f
1 //-----------------------------------------------------------------------
2 // <copyright file="Request.cs" company="Andrew Arnott">
3 // Copyright (c) Andrew Arnott. All rights reserved.
4 // </copyright>
5 //-----------------------------------------------------------------------
7 namespace DotNetOpenAuth.OpenId.Provider {
8 using System;
9 using System.Collections.Generic;
10 using System.Linq;
11 using System.Text;
12 using DotNetOpenAuth.Messaging;
13 using DotNetOpenAuth.OpenId.Messages;
15 /// <summary>
16 /// Implements the <see cref="IRequest"/> interface for all incoming
17 /// request messages to an OpenID Provider.
18 /// </summary>
19 internal abstract class Request : IRequest {
20 /// <summary>
21 /// The OpenIdProvider that received the incoming request.
22 /// </summary>
23 private readonly OpenIdProvider provider;
25 /// <summary>
26 /// The incoming request message.
27 /// </summary>
28 private readonly IDirectedProtocolMessage request;
30 /// <summary>
31 /// The incoming request message cast to its extensible form.
32 /// Or null if the message does not support extensions.
33 /// </summary>
34 private readonly IProtocolMessageWithExtensions extensibleMessage;
36 /// <summary>
37 /// The list of extensions to add to the response message.
38 /// </summary>
39 private List<IOpenIdMessageExtension> responseExtensions = new List<IOpenIdMessageExtension>();
41 /// <summary>
42 /// The last created user agent response, if one has been created
43 /// since the last message-altering change has been made to this object.
44 /// </summary>
45 private UserAgentResponse cachedUserAgentResponse;
47 /// <summary>
48 /// Initializes a new instance of the <see cref="Request"/> class.
49 /// </summary>
50 /// <param name="provider">The Provider.</param>
51 /// <param name="request">The incoming request message.</param>
52 protected Request(OpenIdProvider provider, IDirectedProtocolMessage request) {
53 ErrorUtilities.VerifyArgumentNotNull(provider, "provider");
54 ErrorUtilities.VerifyArgumentNotNull(request, "request");
56 this.provider = provider;
57 this.request = request;
58 this.extensibleMessage = request as IProtocolMessageWithExtensions;
61 #region IRequest Members
63 /// <summary>
64 /// Gets a value indicating whether the response is ready to be sent to the user agent.
65 /// </summary>
66 /// <value></value>
67 /// <remarks>
68 /// This property returns false if there are properties that must be set on this
69 /// request instance before the response can be sent.
70 /// </remarks>
71 public abstract bool IsResponseReady { get; }
73 /// <summary>
74 /// Gets the response to send to the user agent.
75 /// </summary>
76 public UserAgentResponse Response {
77 get {
78 if (this.cachedUserAgentResponse == null && this.IsResponseReady) {
79 if (this.responseExtensions.Count > 0) {
80 var extensibleResponse = this.ResponseMessage as IProtocolMessageWithExtensions;
81 ErrorUtilities.VerifyOperation(extensibleResponse != null, MessagingStrings.MessageNotExtensible, this.ResponseMessage.GetType().Name);
82 foreach (var extension in this.responseExtensions) {
83 // It's possible that a prior call to this property
84 // has already added some/all of the extensions to the message.
85 // We don't have to worry about deleting old ones because
86 // this class provides no facility for removing extensions
87 // that are previously added.
88 if (!extensibleResponse.Extensions.Contains(extension)) {
89 extensibleResponse.Extensions.Add(extension);
94 this.cachedUserAgentResponse = this.provider.Channel.PrepareResponse(this.ResponseMessage);
97 return this.cachedUserAgentResponse;
101 #endregion
103 /// <summary>
104 /// Gets the instance of the hosting <see cref="OpenIdProvider"/>.
105 /// </summary>
106 protected OpenIdProvider Provider {
107 get { return this.provider; }
110 /// <summary>
111 /// Gets the original request message.
112 /// </summary>
113 protected IDirectedProtocolMessage RequestMessage {
114 get { return this.request; }
117 /// <summary>
118 /// Gets the response message, once <see cref="IsResponseReady"/> is <c>true</c>.
119 /// </summary>
120 protected abstract IProtocolMessage ResponseMessage { get; }
122 /// <summary>
123 /// Gets the protocol version used in the request..
124 /// </summary>
125 protected Protocol Protocol {
126 get { return Protocol.Lookup(this.RequestMessage.Version); }
129 #region IRequest Methods
131 /// <summary>
132 /// Adds an extension to the response to send to the relying party.
133 /// </summary>
134 /// <param name="extension">The extension to add to the response message.</param>
135 public void AddResponseExtension(IOpenIdMessageExtension extension) {
136 ErrorUtilities.VerifyArgumentNotNull(extension, "extension");
138 // Because the derived AuthenticationRequest class can swap out
139 // one response message for another (auth vs. no-auth), and because
140 // some response messages support extensions while others don't,
141 // we just add the extensions to a collection here and add them
142 // to the response on the way out.
143 this.responseExtensions.Add(extension);
144 this.ResetUserAgentResponse();
147 /// <summary>
148 /// Gets an extension sent from the relying party.
149 /// </summary>
150 /// <typeparam name="T">The type of the extension.</typeparam>
151 /// <returns>
152 /// An instance of the extension initialized with values passed in with the request.
153 /// </returns>
154 public T GetExtension<T>() where T : IOpenIdMessageExtension, new() {
155 if (this.extensibleMessage != null) {
156 return this.extensibleMessage.Extensions.OfType<T>().SingleOrDefault();
157 } else {
158 return default(T);
162 /// <summary>
163 /// Gets an extension sent from the relying party.
164 /// </summary>
165 /// <param name="extensionType">The type of the extension.</param>
166 /// <returns>
167 /// An instance of the extension initialized with values passed in with the request.
168 /// </returns>
169 public IOpenIdMessageExtension GetExtension(Type extensionType) {
170 ErrorUtilities.VerifyArgumentNotNull(extensionType, "extensionType");
171 if (this.extensibleMessage != null) {
172 return this.extensibleMessage.Extensions.OfType<IOpenIdMessageExtension>().Where(ext => extensionType.IsInstanceOfType(ext)).SingleOrDefault();
173 } else {
174 return null;
178 #endregion
180 /// <summary>
181 /// Resets any user agent response that may have been created already and cached.
182 /// </summary>
183 protected void ResetUserAgentResponse() {
184 this.cachedUserAgentResponse = null;