/// <summary> /// Stop playing /// </summary> /// <returns></returns> public async Task <ServiceActionReturnMessage> Stop() { try { if (ServiceActions.TryGetValue("STOP", out ServiceAction action)) { action.ClearArgumentsValue(); action.SetArgumentValue("InstanceId", "0"); ServiceActionReturnMessage message = await action.InvokeAsync(ServiceTypesString.AVTRANSPORT, serviceControls.Select(c => c).Where(c => c.ServiceType == ServiceTypes.AVTRANSPORT).FirstOrDefault().URI); return(message); } else { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = string.Format("Action not available: Stop") }); } } catch (Exception exception) { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = exception.Message }); } }
/// <summary> /// Set Room on standby /// </summary> /// <returns></returns> public async Task <ServiceActionReturnMessage> EnterManualStandby(string roomUUID) { try { if (ServiceActions.TryGetValue("ENTERMANUALSTANDBY", out ServiceAction action)) { action.ClearArgumentsValue(); action.SetArgumentValue("InstanceId", "0"); action.SetArgumentValue("Room", roomUUID); ServiceActionReturnMessage message = await action.InvokeAsync(ServiceTypesString.AVTRANSPORT, serviceControls.Select(c => c).Where(c => c.ServiceType == ServiceTypes.AVTRANSPORT).FirstOrDefault().URI); return(message); } else { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = string.Format("Action not available: GetCurrentTransportActions") }); } } catch (Exception exception) { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = exception.Message }); } }
/// <summary> /// /// </summary> /// <param name="serverUDN"></param> /// <param name="id"></param> /// <param name="metaData"></param> /// <returns></returns> public async Task <ServiceActionReturnMessage> SetAVTransportUri(bool isContainer, string serverUDN, string containerid, string firstitemid, int index, string metaData) { try { if (ServiceActions.TryGetValue("SETAVTRANSPORTURI", out ServiceAction action)) { action.ClearArgumentsValue(); action.SetArgumentValue("InstanceId", "0"); action.SetArgumentValue("CurrentURI", HtmlExtension.BuildAvTransportUri(isContainer, serverUDN, containerID: containerid, firstItemID: firstitemid, firstItemIndex: index)); action.SetArgumentValue("CurrentURIMetaData", WebUtility.HtmlEncode(metaData)); ServiceActionReturnMessage message = await action.InvokeAsync(ServiceTypesString.AVTRANSPORT, serviceControls.Select(c => c).Where(c => c.ServiceType == ServiceTypes.AVTRANSPORT).FirstOrDefault().URI); return(message); } else { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = string.Format("Action not available: SetAVTransportUri") }); } } catch (Exception exception) { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = exception.Message }); } }
/// <summary> /// Set room mute status /// </summary> /// <param name="roomUUID">Room UUID; string starts with "uuid:..."</param> /// <param name="muteStatus">new muteStatus</param> /// <returns></returns> public async Task <ServiceActionReturnMessage> SetRoomMute(string roomUUID, string muteStatus) { try { if (ServiceActions.TryGetValue("SETROOMMUTE", out ServiceAction action)) { action.ClearArgumentsValue(); action.SetArgumentValue("InstanceId", "0"); action.SetArgumentValue("Room", roomUUID); action.SetArgumentValue("DesiredMute", muteStatus); ServiceActionReturnMessage message = await action.InvokeAsync(ServiceTypesString.RENDERINGCONTROL, serviceControls.Select(c => c).Where(c => c.ServiceType == ServiceTypes.RENDERINGCONTROL).FirstOrDefault().URI); return(message); } else { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = string.Format("Action not available: SetRoomMute") }); } } catch (Exception exception) { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = exception.Message }); } }
/// <summary> /// Create a reference in favorites /// </summary> /// <param name="objectId"></param> /// <returns></returns> public async Task <ServiceActionReturnMessage> CreateReference(string objectId) { try { if (ServiceActions.TryGetValue("CREATEREFERENCE", out ServiceAction action)) { action.ClearArgumentsValue(); action.SetArgumentValue("ContainerID", "0/Favorites/MyFavorites"); action.SetArgumentValue("ObjectID", objectId); ServiceActionReturnMessage message = await action.InvokeAsync(ServiceTypesString.CONTENTDIRECTORY, serviceControls.Select(c => c).Where(c => c.ServiceType == ServiceTypes.CONTENTDIRECTORY).FirstOrDefault().URI); return(message); } else { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = string.Format("Action not available: CreateReference") }); } } catch (Exception exception) { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = exception.Message }); } }
/// <summary> /// Destroy Object /// </summary> /// <param name="objectId"></param> /// <returns></returns> public async Task <ServiceActionReturnMessage> DestroyObject(string objectId) { try { if (ServiceActions.TryGetValue("DESTROYOBJECT", out ServiceAction action)) { action.ClearArgumentsValue(); action.SetArgumentValue("ObjectID", objectId); ServiceActionReturnMessage message = await action.InvokeAsync(ServiceTypesString.CONTENTDIRECTORY, serviceControls.Select(c => c).Where(c => c.ServiceType == ServiceTypes.CONTENTDIRECTORY).FirstOrDefault().URI); return(message); } else { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = string.Format("Action not available: DestroyObject") }); } } catch (Exception exception) { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = exception.Message }); } }
/// <summary> /// Add item to queue /// </summary> /// <param name="containerId"></param> /// <param name="position"></param> /// <returns></returns> public async Task <ServiceActionReturnMessage> AddItemToQueue(string containerId, int position) { try { if (ServiceActions.TryGetValue("ADDITEMTOQUEUE", out ServiceAction action)) { action.ClearArgumentsValue(); action.SetArgumentValue("QueueID", RaumFeldStaticDefinitions.PLAYLIST); action.SetArgumentValue("ContainerID", containerId); action.SetArgumentValue("Position", position.ToString()); ServiceActionReturnMessage message = await action.InvokeAsync(ServiceTypesString.CONTENTDIRECTORY, serviceControls.Select(c => c).Where(c => c.ServiceType == ServiceTypes.CONTENTDIRECTORY).FirstOrDefault().URI); return(message); } else { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = string.Format("Action not available: Browse") }); } } catch (Exception exception) { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = exception.Message }); } }
//public async Task<DIDLLite> UnlikeCurrent(string id) //{ // try // { // return null; // } // catch // { // return null; // } //} #endregion #region RenderControl Methods /// <summary> /// Change main volume /// </summary> /// <param name="amount">From -127 to 127, Step 1</param> /// <returns></returns> public async Task <ServiceActionReturnMessage> ChangeVolume(string amount) { try { if (ServiceActions.TryGetValue("CHANGEVOLUME", out ServiceAction action)) { action.ClearArgumentsValue(); action.SetArgumentValue("InstanceId", "0"); action.SetArgumentValue("Amount", amount); ServiceActionReturnMessage message = await action.InvokeAsync(ServiceTypesString.RENDERINGCONTROL, serviceControls.Select(c => c).Where(c => c.ServiceType == ServiceTypes.RENDERINGCONTROL).FirstOrDefault().URI); return(message); } else { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = string.Format("Action not available: ChangeVolume") }); } } catch (Exception exception) { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = exception.Message }); } }
/// <summary> /// Create new queue in playlists /// To be able to add songs and reorder items /// </summary> /// <returns></returns> public async Task <ServiceActionReturnMessage> CreateQueue() { try { if (ServiceActions.TryGetValue("CREATEQUEUE", out ServiceAction action)) { action.ClearArgumentsValue(); action.SetArgumentValue("DesiredName", RaumFeldStaticDefinitions.PLAYLIST); action.SetArgumentValue("ContainerID", RaumFeldStaticDefinitions.PLAYLISTBASE); ServiceActionReturnMessage message = await action.InvokeAsync(ServiceTypesString.CONTENTDIRECTORY, serviceControls.Select(c => c).Where(c => c.ServiceType == ServiceTypes.CONTENTDIRECTORY).FirstOrDefault().URI); if (message.ActionStatus == ActionStatus.Okay) { Dictionary <string, string> results = new Dictionary <string, string> { ["GivenName"] = action.GetArgumentValue("GivenName"), ["QueueID"] = action.GetArgumentValue("QueueID") }; message.ReturnValue = results; return(message); } else { return(message); } } else { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = string.Format("Action not available: CreateQueue") }); } } catch (Exception exception) { throw new Exception(); return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = exception.Message }); } }
/// <summary> /// Get info of current track /// </summary> /// <returns></returns> public async Task <ServiceActionReturnMessage> GetPositionInfo() { try { if (ServiceActions.TryGetValue("GETPOSITIONINFO", out ServiceAction action)) { action.ClearArgumentsValue(); action.SetArgumentValue("InstanceId", "0"); ServiceActionReturnMessage message = await action.InvokeAsync(ServiceTypesString.AVTRANSPORT, serviceControls.Select(c => c).Where(c => c.ServiceType == ServiceTypes.AVTRANSPORT).FirstOrDefault().URI); if (message.ActionStatus == ActionStatus.Okay) { Dictionary <string, string> positionInfo = new Dictionary <string, string> { ["Track"] = action.GetArgumentValue("Track"), ["TrackDuration"] = action.GetArgumentValue("TrackDuration"), ["TrackMetaData"] = action.GetArgumentValue("TrackMetaData"), ["TrackURI"] = action.GetArgumentValue("TrackUri") }; message.ReturnValue = positionInfo; return(message); } else { return(message); } } else { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = string.Format("Action not available: GetPositionInfo") }); } } catch (Exception exception) { throw new Exception(); return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = exception.Message }); } }
/// <summary> /// BrowseMetaData /// </summary> /// <param name="Id"></param> /// <returns></returns> public async Task <ServiceActionReturnMessage> BrowseMetaData(string Id) { try { if (ServiceActions.TryGetValue("BROWSE", out ServiceAction action)) { action.ClearArgumentsValue(); action.SetArgumentValue("ObjectID", Id); action.SetArgumentValue("BrowseFlag", "BrowseMetadata"); action.SetArgumentValue("Filter", "*"); action.SetArgumentValue("StartingIndex", "0"); action.SetArgumentValue("RequestedCount", "0"); action.SetArgumentValue("SortCriteria", ""); ServiceActionReturnMessage message = await action.InvokeAsync(ServiceTypesString.CONTENTDIRECTORY, serviceControls.Select(c => c).Where(c => c.ServiceType == ServiceTypes.CONTENTDIRECTORY).FirstOrDefault().URI); if (message.ActionStatus == ActionStatus.Okay) { string result = action.GetArgumentValue("Result"); message.ReturnValue = result; return(message); } else { return(message); } } else { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = string.Format("Action not available: Browse") }); } } catch (Exception exception) { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = exception.Message }); } }
/// <summary> /// Get the possible transport actions /// </summary> /// <returns>String[] with all possible actions</returns> public async Task <ServiceActionReturnMessage> GetCurrentTransportActions() { try { if (ServiceActions.TryGetValue("GETCURRENTTRANSPORTACTIONS", out ServiceAction action)) { action.ClearArgumentsValue(); action.SetArgumentValue("InstanceId", "0"); ServiceActionReturnMessage message = await action.InvokeAsync(ServiceTypesString.AVTRANSPORT, serviceControls.Select(c => c).Where(c => c.ServiceType == ServiceTypes.AVTRANSPORT).FirstOrDefault().URI); if (message.ActionStatus == ActionStatus.Okay) { string result = action.GetArgumentValue("Actions"); string[] stringSeparators = new string[] { "," }; // Split delimited by another string and return all non-empty elements. message.ReturnValue = result.Split(stringSeparators, StringSplitOptions.RemoveEmptyEntries); return(message); } else { return(message); } } else { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = string.Format("Action not available: GetCurrentTransportActions") }); } } catch (Exception exception) { throw new Exception(); return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = exception.Message }); } }
/// <summary> /// Get main volume /// </summary> /// <returns></returns> public async Task <ServiceActionReturnMessage> GetVolume() { try { if (ServiceActions.TryGetValue("GETVOLUME", out ServiceAction action)) { action.ClearArgumentsValue(); action.SetArgumentValue("InstanceId", "0"); action.SetArgumentValue("Channel", "Master"); ServiceActionReturnMessage message = await action.InvokeAsync(ServiceTypesString.RENDERINGCONTROL, serviceControls.Select(c => c).Where(c => c.ServiceType == ServiceTypes.RENDERINGCONTROL).FirstOrDefault().URI); if (message.ActionStatus == ActionStatus.Okay) { message.ReturnValue = double.Parse(action.GetArgumentValue("CurrentVolume")); return(message); } else { return(message); } } else { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = string.Format("Action not available: GetVolume") }); } } catch (Exception exception) { throw new Exception(); return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = exception.Message }); } }
/// <summary> /// Get current playmode /// </summary> /// <returns></returns> public async Task <ServiceActionReturnMessage> GetTransportSettings() { try { if (ServiceActions.TryGetValue("GETTRANSPORTSETTINGS", out ServiceAction action)) { action.ClearArgumentsValue(); action.SetArgumentValue("InstanceId", "0"); ServiceActionReturnMessage message = await action.InvokeAsync(ServiceTypesString.AVTRANSPORT, serviceControls.Select(c => c).Where(c => c.ServiceType == ServiceTypes.AVTRANSPORT).FirstOrDefault().URI); if (message.ActionStatus == ActionStatus.Okay) { message.ReturnValue = action.GetArgumentValue("Playmode"); return(message); } else { return(message); } } else { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = string.Format("Action not available: GetTransportSettings") }); } } catch (Exception exception) { throw new Exception(); return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = exception.Message }); } }
/// <summary> /// Search elements /// Important: Search only works within the right containerID /// </summary> /// <param name="containerId"></param> /// <param name="searchCriteria"></param> /// <param name="start"></param> /// <param name="limit"></param> /// <returns></returns> public async Task <ServiceActionReturnMessage> Search(string containerId, string searchCriteria, int start, int limit = 10) { try { if (ServiceActions.TryGetValue("SEARCH", out ServiceAction action)) { List <IElement> elements = new List <IElement>(); //bool found = false; action.ClearArgumentsValue(); action.SetArgumentValue("ContainerID", containerId); action.SetArgumentValue("SearchCriteria", string.Format("dc:title contains \"{0}\"", searchCriteria)); action.SetArgumentValue("Filter", "*"); action.SetArgumentValue("StartingIndex", start.ToString()); action.SetArgumentValue("RequestedCount", limit.ToString()); action.SetArgumentValue("SortCriteria", ""); ServiceActionReturnMessage message = await action.InvokeAsync(ServiceTypesString.CONTENTDIRECTORY, serviceControls.Select(c => c).Where(c => c.ServiceType == ServiceTypes.CONTENTDIRECTORY).FirstOrDefault().URI); if (message.ActionStatus == ActionStatus.Okay) { string result = action.GetArgumentValue("Result"); DIDLLite didlliteResult = result.Deserialize <DIDLLite>(); if (string.IsNullOrEmpty(result) || didlliteResult == null) { return(null); } foreach (DIDLContainer container in didlliteResult.Containers) { switch (container.Title) { case "Zones": case "Renderers": case "Search": break; default: IElement element = Prism.Unity.Windows.PrismUnityApplication.Current.Container.Resolve <ElementContainer>(new ResolverOverride[] { new ParameterOverride("didl", container) }); elements.Add(element); break; } } foreach (DIDLItem item in didlliteResult.Items) { IElement element = Prism.Unity.Windows.PrismUnityApplication.Current.Container.Resolve <ElementItem>(new ResolverOverride[] { new ParameterOverride("didl", item) }); elements.Add(element); } message.ReturnValue = elements; return(message); } else { return(message); } } else { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = string.Format("Action not available: Browse") }); } } catch (Exception exception) { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = exception.Message }); } }
/// <summary> /// BrowseMetaData /// </summary> /// <param name="Id"></param> /// <returns></returns> public async Task <ServiceActionReturnMessage> BrowseMetaData(string Id) { try { if (ServiceActions.TryGetValue("BROWSE", out ServiceAction action)) { ElementBase element = null; action.ClearArgumentsValue(); action.SetArgumentValue("ObjectID", Id); action.SetArgumentValue("BrowseFlag", "BrowseMetadata"); action.SetArgumentValue("Filter", "*"); action.SetArgumentValue("StartingIndex", "0"); action.SetArgumentValue("RequestedCount", "0"); action.SetArgumentValue("SortCriteria", ""); ServiceActionReturnMessage message = await action.InvokeAsync(ServiceTypesString.CONTENTDIRECTORY, serviceControls.Select(c => c).Where(c => c.ServiceType == ServiceTypes.CONTENTDIRECTORY).FirstOrDefault().URI); if (message.ActionStatus == ActionStatus.Okay) { string result = action.GetArgumentValue("Result"); DIDLLite didlliteResult = result.Deserialize <DIDLLite>(); if (string.IsNullOrEmpty(result) || didlliteResult == null) { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = string.Format("Parsing error DIDLLite-string") }); } foreach (DIDLContainer container in didlliteResult.Containers) { switch (container.Title) { case "Zones": case "Renderers": case "Search": break; default: //element = PrismUnityApplication.Current.Container.Resolve<ElementContainer>(new ResolverOverride[] // { // new ParameterOverride("didl", container) // }); element = PrismUnityApplication.Current.Container.Resolve <ElementBase>("DIDLContainer", new DependencyOverride(typeof(IEventAggregator), eventAggregator), new DependencyOverride(typeof(ICachingService), cachingService), new DependencyOverride(typeof(DIDLContainer), container)); break; } } foreach (DIDLItem item in didlliteResult.Items) { //element = PrismUnityApplication.Current.Container.Resolve<ElementItem>(new ResolverOverride[] // { // new ParameterOverride("didl", item) // }); element = PrismUnityApplication.Current.Container.Resolve <ElementBase>("DIDLItem", new DependencyOverride(typeof(IEventAggregator), eventAggregator), new DependencyOverride(typeof(ICachingService), cachingService), new DependencyOverride(typeof(DIDLItem), item)); } message.ReturnValue = element; return(message); } else { return(message); } } else { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = string.Format("Action not available: Browse") }); } } catch (Exception exception) { throw new Exception(); return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionMessage = exception.Message }); } }
/// <summary> /// Invoke Action /// </summary> /// <param name="serviceType"></param> /// <param name="serviceUrl"></param> /// <returns></returns> public async Task <ServiceActionReturnMessage> InvokeAsync(string serviceType, string serviceUrl) { try { StringBuilder xml = new StringBuilder(); xml.Append("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); xml.Append("<s:Envelope s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">"); xml.Append("<s:Body>"); xml.Append("<u:" + Name + " xmlns:u=\"" + serviceType + "\">"); foreach (Argument arg in ArgumentList) { if (arg.Direction.ToUpper() == "IN") { xml.Append("<" + arg.Name + ">" + arg.Value + "</" + arg.Name + ">"); } } xml.Append("</u:" + Name + ">"); xml.Append("</s:Body>"); xml.Append("</s:Envelope>"); using (HttpClient client = new HttpClient()) { using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, new Uri(serviceUrl))) { request.Headers.Add("SOAPACTION", "\"" + serviceType + "#" + Name + "\""); request.Headers.Add("User-Agent", "RaumfeldControl/0.0 RaumfeldProtocol/1"); /* RaumfeldControl/3.6 RaumfeldProtocol/399 Build => https://github.com/masmu/pulseaudio-dlna/issues/227 */ request.Headers.Add("Accept-Language", "en"); request.Headers.Add("ContentType", "text/xml; charset=\"utf - 8\""); //request.Method = HttpMethod.Post; using (HttpStringContent requestContent = new HttpStringContent(xml.ToString(), Windows.Storage.Streams.UnicodeEncoding.Utf8, "text/xml")) { request.Content = requestContent; using (HttpResponseMessage response = await client.SendRequestAsync(request)) { if (response.StatusCode == HttpStatusCode.Ok) { string xmlResponse = await response.Content.ReadAsStringAsync(); XmlDocument xmlDocument = new XmlDocument(); xmlDocument.LoadXml(xmlResponse); XmlNodeList xmlNodes = xmlDocument.SelectNodes("//*"); var results = ArgumentList.Join(xmlNodes, arg => arg.Name.ToUpper(), xmlNode => xmlNode.NodeName.ToUpper(), (arg, xmlNode) => new { Argument = arg, XmlNode = xmlNode }) .Where(selection => selection.Argument.Direction.ToUpper() == "OUT"); if (results.Count() != 0) { foreach (var item in results) { item.Argument.Value = item.XmlNode.InnerText; } } return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Okay, ActionMessage = string.Empty }); } else { ServiceActionReturnMessage returnMessage = new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error }; string xmlResponse = await response.Content.ReadAsStringAsync(); XmlDocument xmlDocument = new XmlDocument(); xmlDocument.LoadXml(xmlResponse); XmlNodeList xmlNodes = xmlDocument.SelectNodes("//*"); IXmlNode errorNode = xmlNodes.Select(n => n).Where(n => n.NodeName.ToUpper() == "UPNPERROR").FirstOrDefault(); if (errorNode != null) { foreach (var item in errorNode.ChildNodes) { switch (item.NodeName.ToUpper()) { case "ERRORCODE": returnMessage.ActionErrorCode = int.Parse(item.InnerText); break; case "ERRORDESCRIPTION": returnMessage.ActionMessage = item.InnerText; break; } } } return(returnMessage); } } } } } } catch (Exception exception) { return(new ServiceActionReturnMessage() { ActionStatus = ActionStatus.Error, ActionErrorCode = exception.HResult, ActionMessage = exception.Message }); } }