6using System.Threading.Tasks;
19 private readonly Dictionary<string, UPnPArgument> argumentByName =
new Dictionary<string, UPnPArgument>();
21 private readonly XmlElement xml;
23 private readonly
string name;
27 List<UPnPArgument>
Arguments =
new List<UPnPArgument>();
32 foreach (XmlNode N
in Xml.ChildNodes)
37 this.name = N.InnerText;
41 foreach (XmlNode N2
in N.ChildNodes)
43 if (N2.LocalName ==
"argument")
47 this.argumentByName[Argument.
Name] = Argument;
60 public XmlElement
Xml => this.xml;
65 public string Name => this.name;
83 public object Invoke(out Dictionary<string, object> OutputValues, params KeyValuePair<string, object>[] InputValues)
85 return this.
Invoke(out OutputValues, 10000, InputValues);
94 public object Invoke(Dictionary<string, object> InputValues, out Dictionary<string, object> OutputValues)
96 return this.
Invoke(InputValues, out OutputValues, 10000);
106 public object Invoke(out Dictionary<string, object> OutputValues,
int Timeout, params KeyValuePair<string, object>[] InputValues)
108 Dictionary<string, object> InputValues2 =
new Dictionary<string, object>();
110 foreach (KeyValuePair<string, object> P
in InputValues)
111 InputValues2[P.Key] = P.Value;
113 return this.
Invoke(InputValues2, out OutputValues, Timeout);
123 public object Invoke(Dictionary<string, object> InputValues, out Dictionary<string, object> OutputValues,
int Timeout)
125 KeyValuePair<object, Dictionary<string, object>> Result = this.
InvokeAsync(InputValues, Timeout).Result;
126 OutputValues = Result.Value;
136 public Task<KeyValuePair<object, Dictionary<string, object>>>
InvokeAsync(
int Timeout, params KeyValuePair<string, object>[] InputValues)
138 Dictionary<string, object> InputValues2 =
new Dictionary<string, object>();
140 foreach (KeyValuePair<string, object> P
in InputValues)
141 InputValues2[P.Key] = P.Value;
152 public async Task<KeyValuePair<object, Dictionary<string, object>>>
InvokeAsync(Dictionary<string, object> InputValues,
int Timeout)
154 Dictionary<string, object> OutputValues;
155 StringBuilder Soap =
new StringBuilder();
157 object Result =
null;
160 Soap.AppendLine(
"<?xml version=\"1.0\"?>");
161 Soap.AppendLine(
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">");
162 Soap.AppendLine(
"<s:Body>");
164 Soap.Append(this.name);
165 Soap.Append(
" xmlns:u=\"");
167 Soap.AppendLine(
"\">");
174 Soap.Append(Argument.
Name);
177 if (InputValues.TryGetValue(Argument.
Name, out
object Value) &&
184 Soap.Append(Argument.
Name);
190 Soap.Append(this.name);
191 Soap.AppendLine(
">");
192 Soap.AppendLine(
"</s:Body>");
193 Soap.AppendLine(
"</s:Envelope>");
195 using (HttpClient HttpClient =
new HttpClient())
197 HttpClient.Timeout = TimeSpan.FromMilliseconds(Timeout);
198 HttpClient.DefaultRequestHeaders.ExpectContinue =
false;
200 HttpContent Body =
new StringContent(Soap.ToString(), Encoding.UTF8,
"text/xml");
201 Body.Headers.Add(
"SOAPACTION",
"\"" + this.parent.Service.ServiceType +
"#" +
this.name +
"\"");
203 HttpResponseMessage Response = await HttpClient.PostAsync(this.parent.Service.ControlURI, Body);
204 Stream Stream = await Response.Content.ReadAsStreamAsync();
205 byte[] Bin = await Stream.ReadAllAsync();
209 Bin,
this.parent.Service.ControlURI);
213 XmlDocument ResponseXml = Decoded.Decoded as XmlDocument
214 ??
throw new Exception(
"Expected XML response to UPnP action request.");
216 if (ResponseXml.DocumentElement is
null ||
217 ResponseXml.DocumentElement.LocalName !=
"Envelope" ||
218 ResponseXml.DocumentElement.NamespaceURI !=
"http://schemas.xmlsoap.org/soap/envelope/")
220 throw new Exception(
"Unexpected XML response returned.");
223 XmlElement ResponseBody = GetChildElement(ResponseXml.DocumentElement,
"Body",
"http://schemas.xmlsoap.org/soap/envelope/")
224 ??
throw new Exception(
"Response body not found.");
226 XmlElement ActionResponse = GetChildElement(ResponseBody, this.name +
"Response", this.parent.Service.ServiceType);
227 if (ActionResponse is
null)
229 XmlElement ResponseFault = GetChildElement(ResponseBody,
"Fault",
"http://schemas.xmlsoap.org/soap/envelope/")
230 ??
throw new Exception(
"Unable to parse response.");
232 string FaultCode =
string.Empty;
233 string FaultString =
string.Empty;
234 string UPnPErrorCode =
string.Empty;
235 string UPnPErrorDescription =
string.Empty;
237 foreach (XmlNode N
in ResponseFault.ChildNodes)
242 FaultCode = N.InnerText;
246 FaultString = N.InnerText;
250 foreach (XmlNode N2
in N.ChildNodes)
252 switch (N2.LocalName)
255 foreach (XmlNode N3
in N2.ChildNodes)
257 switch (N3.LocalName)
260 UPnPErrorCode = N3.InnerText;
263 case "errorDescription":
264 UPnPErrorDescription = N3.InnerText;
275 throw new UPnPException(FaultCode, FaultString, UPnPErrorCode, UPnPErrorDescription);
280 OutputValues =
new Dictionary<string, object>();
282 foreach (XmlNode N
in ActionResponse.ChildNodes)
288 if (this.argumentByName.TryGetValue(E.LocalName, out
UPnPArgument Argument2))
290 if (!((Variable = this.parent.GetVariable(Argument2.RelatedStateVariable)) is
null))
292 object Value2 = Variable.XmlStringToValue(E.InnerText);
293 OutputValues[E.LocalName] = Value2;
298 if (Argument2.ReturnValue && Result is
null)
306 OutputValues[E.LocalName] = E.InnerXml;
314 OutputValues[E.LocalName] = E.InnerXml;
322 return new KeyValuePair<object, Dictionary<string, object>>(Result, OutputValues);
325 private static XmlElement GetChildElement(XmlElement E,
string LocalName,
string Namespace)
329 foreach (XmlNode N
in E.ChildNodes)
331 E2 = N as XmlElement;
335 if (E2.LocalName == LocalName && E2.NamespaceURI == Namespace)
349 if (AttributeValue is
null || AttributeValue.IndexOfAny(reservedCharacters) < 0)
350 return AttributeValue;
352 return AttributeValue.
353 Replace(
"&",
"&").
354 Replace(
"<",
"<").
355 Replace(
">",
">").
356 Replace(
"\"",
""").
357 Replace(
"'",
"'");
360 private static readonly
char[] reservedCharacters =
new char[] {
'&',
'<',
'>',
'"',
'\'' };
Contains information about a response to a content request.
void AssertOk()
Asserts response is OK.
Static class managing encoding and decoding of internet content.
static Task< ContentResponse > DecodeAsync(string ContentType, byte[] Data, Encoding Encoding, KeyValuePair< string, string >[] Fields, Uri BaseUri)
Decodes an object.
const string DefaultContentType
Default content type for XML documents.
Contains the information provided in a Service Description Document, downloaded from a service in the...
Contains information about an action.
object Invoke(out Dictionary< string, object > OutputValues, int Timeout, params KeyValuePair< string, object >[] InputValues)
Invokes the action.
Task< KeyValuePair< object, Dictionary< string, object > > > InvokeAsync(int Timeout, params KeyValuePair< string, object >[] InputValues)
Invokes the action.
object Invoke(Dictionary< string, object > InputValues, out Dictionary< string, object > OutputValues)
Invokes the action.
object Invoke(Dictionary< string, object > InputValues, out Dictionary< string, object > OutputValues, int Timeout)
Invokes the action.
UPnPArgument[] Arguments
Service Arguments.
object Invoke(out Dictionary< string, object > OutputValues, params KeyValuePair< string, object >[] InputValues)
Invokes the action.
XmlElement Xml
Underlying XML definition.
static string XmlAttributeEncode(string AttributeValue)
Encodes an XML attribute.
async Task< KeyValuePair< object, Dictionary< string, object > > > InvokeAsync(Dictionary< string, object > InputValues, int Timeout)
Invokes the action.
Contains information about an argument.
string RelatedStateVariable
Related State Variable
ArgumentDirection Direction
Argument Direction
Contains information about a state variable.
ArgumentDirection
Direction of action arguments.