WCF offers two options for ResponseFormat attribute in WebGet annotation in ServiceContract.
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebGet(UriTemplate = "greet/{value}", BodyStyle = WebMessageBodyStyle.Bare)]
string GetData(string value);
[OperationContract]
[WebGet(UriTemplate = "foo", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
string Foo();
The options for ResponseFormat are WebMessageFormat.Json and WebMessageFormat.Xml. Is it possible to write my own web message format? I would like that when client calls foo() method he gets raw string - without json or xml wrappers.
Try using
BodyStyle = WebMessageBodyStyle.Bare
Then return a System.IO.Stream from your function.
Here's some code I use to return an image out of a database, but accessible via a URL:
[OperationContract()]
[WebGet(UriTemplate = "Person/{personID}/Image", BodyStyle = WebMessageBodyStyle.Bare)]
System.IO.Stream GetImage(string personID);
Implementation:
public System.IO.Stream GetImage(string personID)
{
// parse personID, call DB
OutgoingWebResponseContext context = WebOperationContext.Current.OutgoingResponse;
if (image_not_found_in_DB)
{
context.StatusCode = System.Net.HttpStatusCode.Redirect;
context.Headers.Add(System.Net.HttpResponseHeader.Location, url_of_a_default_image);
return null;
}
// everything is OK, so send image
context.Headers.Add(System.Net.HttpResponseHeader.CacheControl, "public");
context.ContentType = "image/jpeg";
context.LastModified = date_image_was_stored_in_database;
context.StatusCode = System.Net.HttpStatusCode.OK;
return new System.IO.MemoryStream(buffer_containing_jpeg_image_from_database);
}
In your case, to return a raw string, set the ContentType to something like "text/plain" and return your data as a stream. At a guess, something like this:
return new System.IO.MemoryStream(ASCIIEncoding.Default.GetBytes(string_to_send));
WebGetAttribute is shipped by Microsoft, and I don't think you can extend WebMessageFormat. However you could probably extend the WebHttpBinding that uses WebGetAttribute. You could add your own attribute like
[WebGet2(UriTemplate = "foo", ResponseFormat = WebMessageFormat2.PlainText)]
string Foo();
In general, customizing the message layout in WCF is called custom message encoder/encoding. Microsoft provides an example: Custom Message Encoder: Compression Encoder. Also another common extension people do is to extend behavior to add custom error handling, so you could look for some example in that direction.
I implemented this attribute like this, maybe it will help someone in the future:
[AttributeUsage(AttributeTargets.Method)]
public class WebGetText : Attribute, IOperationBehavior
{
public void Validate(OperationDescription operationDescription)
{
}
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
dispatchOperation.Formatter = new Formatter(dispatchOperation.Formatter);
}
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
{
}
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
{
}
}
public class Formatter : IDispatchMessageFormatter
{
IDispatchMessageFormatter form;
public Formatter (IDispatchMessageFormatter form)
{
this.form = form;
}
public void DeserializeRequest(Message message, object[] parameters)
{
form.DeserializeRequest(message, parameters)
}
public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
{
IEnumerable<object> cl = (IEnumerable<object>)result;
StringBuilder csvdata = new StringBuilder();
foreach (object userVariableClass in cl) {
Type type = userVariableClass.GetType();
PropertyInfo[] fields = type.GetProperties();
// Dim header As String = String.Join(";", fields.Select(Function(f) f.Name + ": " + f.GetValue(userVariableClass, Nothing).ToString()).ToArray())
// csvdata.AppendLine("")
// csvdata.AppendLine(header)
csvdata.AppendLine(ToCsvFields(";", fields, userVariableClass));
csvdata.AppendLine("");
csvdata.AppendLine("=====EOF=====");
csvdata.AppendLine("");
}
Message msg = WebOperationContext.Current.CreateTextResponse(csvdata.ToString());
return msg;
}
public static string ToCsvFields(string separator, PropertyInfo[] fields, object o)
{
StringBuilder linie = new StringBuilder();
foreach (PropertyInfo f in fields) {
if (linie.Length > 0) {
}
object x = f.GetValue(o, null);
if (x != null) {
linie.AppendLine(f.Name + ": " + x.ToString());
} else {
linie.AppendLine(f.Name + ": Nothing");
}
}
return linie.ToString();
}
}
There is one way how to achieve this if you're dealing with HTTP, it's not exactly nice, but I thought I could mention it.
You can set the return type of your method to void and just output your raw string directly into the response.
[OperationContract]
[WebGet(UriTemplate = "foo")]
void Foo()
{
HttpContext.Current.Response.Write("bar");
}
Related
I have created a WCF webservice returning json format data. My code is like below:
String sJSONdata = "";
StreamReader reader = new StreamReader(data);
sJSONdata = reader.ReadToEnd();
//'now convert the JSON into a data table
DataTable dt = GetJSONTable(sJSONdata);
dt.TableName = "Customer";
Dictionary<string, string> dict = new Dictionary<string, string>();
foreach (DataRow rs in dt.Rows)
{
dict = new Dictionary<string, string>();
foreach (DataColumn col in dt.Columns)
{
dict.Add(col.ColumnName, rs[col].ToString());
}
}
return (new JavaScriptSerializer().Serialize(dict));
And I get the following output:
{ "SampleServiceResult":
"{\"Id\":\"1\",\"Name\":\"xyz\",\"email\":\"xya#test.com\"}" }
But I want the output as below:
{ "SampleServiceResult":
{"Id":"1","Name":"xyz","email":"xya#test.com"} }
In the output it adds "\" escape character. How can I remove this and return valid json?
I have tried to replace "\" but it doesn't work.
Thanks
I have got the expected out by applying following changes in my code:
Changed return type from String to Stream
Replaced the below code
return (new JavaScriptSerializer().Serialize(dict));
with
WebOperationContext.Current.OutgoingResponse.ContentType = "application/json; charset=utf-8";
return new MemoryStream(Encoding.UTF8.GetBytes(sData));
Thanks everybody for help and support. May it will help someone.
It is better to let WCF take care of the serialization rather then doing it yourself.
You can use WebGet attribute and specify the response format for your operation contract.
Also, as pointed out in the comments, you could return your own .NET class instead of a Dictionary.
The operation contract could be something similar to this:
[OperationContract]
[WebGet(UriTemplate = "/GetCustomer", ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare)]
Customer GetCustomer();
with the following data contract:
[DataContract]
public class Customer
{
[DataMember]
public string Id { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Email { get; set; }
}
You could then implement the operation contract with code similar to this:
public Customer GetCustomer()
{
Customer customer = GetCustomerData(); //Get the data and return a customer object
return customer;
}
I would like to accept a post from a 3rd party tool which posts a complex json object. For this question we can assume an object like this:
{
a: "a value",
b: "b value",
c: "c value",
d: {
a: [1,2,3]
}
}
my .net code looks like
asmx:
[WebMethod]
public bool AcceptPush(ABCObject ObjectName) { ... }
class.cs
public class ABCObject
{
public string a;
public string b;
public string c;
ABCSubObject d;
}
public class ABCSubObject
{
public int[] a;
}
This all works perfectly if I pass the object when it is wrapped and named "ObjectName":
{
ObjectName:
{
a: "a value",
b: "b value",
c: "c value",
d: {
a: [1,2,3]
}
}
}
But fails without the object wrapped in an named object. Which is what is posted.
{
a: "a value",
b: "b value",
c: "c value",
d: {
a: [1,2,3]
}
}
I can accept this or any post with a Handler (ashx), but is this possible using a vanilla .Net Webservice (asmx)?
I also tried combinations of:
[WebMethod(EnableSession = false)]
[WebInvoke(
Method = "POST",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate="{ObjectName}")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
I suspect UriTemplate or some missing BodyTemplate would work.
You mignt need to remove WebMethod's parameter, and map json string to ABCObject manually.
[WebMethod]
public bool AcceptPush()
{
ABCObject ObjectName = null;
string contentType = HttpContext.Current.Request.ContentType;
if (false == contentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase)) return false;
using (System.IO.Stream stream = HttpContext.Current.Request.InputStream)
using (System.IO.StreamReader reader = new System.IO.StreamReader(stream))
{
stream.Seek(0, System.IO.SeekOrigin.Begin);
string bodyText = reader.ReadToEnd(); bodyText = bodyText == "" ? "{}" : bodyText;
var json = Newtonsoft.Json.Linq.JObject.Parse(bodyText);
ObjectName = Newtonsoft.Json.JsonConvert.DeserializeObject<ABCObject>(json.ToString());
}
return true;
}
Hope this helps.
I am attempting to build a Restful WCF Service which returns data in JSON format. My firsts methods work fine but when I try return a collection my test program receive the next exception:
Unable to write data to the transport connection. An existing connection was forcibly closed by the remote host.
My Service code:
[ServiceContract]
public interface IService
{
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "/GetModes")]
OGetModesResponse OGetModes(OGetModesRequest oGetModes);
}
[DataContract]
public class OGetModesRequest
{
private String m_sTicket;
[DataMember]
public String prTicket
{
get { return m_sTicket; }
set { m_sTicket = value; }
}
}
[DataContract]
public class OGetModesResponse
{
[DataMember]
public string sTicket;
[DataMember]
public emStatus emStatus;
[DataMember]
public IList<CTMode> aoModes;
}
And my test program:
OGetModesRequest oGetModes = new OGetModesRequest { prTicket = sTicket };
ser = new DataContractJsonSerializer(typeof(OGetModesRequest));
mem = new MemoryStream();
ser.WriteObject(mem, oGetModes);
webClient = new WebClient();
webClient.Headers["Content-type"] = "application/json";
webClient.Encoding = Encoding.UTF8;
//Exception here
bData = webClient.UploadData("http://localhost:26104/Service.svc/GetModes", "POST", mem.ToArray());
stream = new MemoryStream(bData);
obj = new DataContractJsonSerializer(typeof(OGetModesResponse));
OGetModesResponse OResultModes = obj.ReadObject(stream) as OGetModesResponse;
I debug my services and works fine. What can be happening?
Thanks for help.
Edit (solution):
CTMode is a class used by managing object that I obtain using NHibernate so I create a new class serializable called CMode
[DataContract]
public class OGetModesResponse
{
[DataMember]
public string sTicket;
[DataMember]
public emStatus emStatus;
[DataMember]
public IList<CMode> aoModes;
}
[Serializable]
public class CMode
{
public Int32 nId;
public Int32 nCode;
public String sName;
}
Try to check inner exception and add some logging/ trace on the server.
There are few possibilities for your (generic) error as you may not be aware about inner exception:
object CTMode is missing DataContract, DataMember attribute.
object CTMode is an enum that missing attributes or has incorrect value that cannot be serialized
previous connection is not closed correctly
there is a proxy server on the way and you need to bypassed it
[DataContract]
public abstract class BusMessage
{
[DataMember(Name = "encoding")]
public string Encoding { get; set; }
[DataMember(Name = "type")]
public virtual MessageType Type
{
get { return _type; }
private set { _type = value; }
}
}
[DataContract]
public class BusTextMessage : BusMessage
{
[DataMember(Name = "type")]
public override MessageType Type
{
get { return MessageType.Text; }
}
[DataMember(Name = "payload")]
public string Payload { get; set; }
}
[ServiceContract]
[ServiceKnownType("GetKnownTypes", typeof(Helper))]
public interface ICommunicationService
{
[WebInvoke(Method = "POST",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "/SendMessage")]
string SendMessage(BusMessage jsonMessage);
}
}
When I send request with Postman chrome, if I don't add __type as "__type":"BusTextMessage:#TransportModels.Messages" the object won't be serialized properly because it doesn't know how to instantiate BusMessage class. I have already defined Type property which defines the type of message. Is there any possibility to override __type behaviour for example return proper implementation depending on Type property? I don't want anyone to put __type information to json manually so is there an option to edit json before deserialization and add __type property manually to json if it doesn't exist? For example I want to do something like this:
public void BeforeDeserialization(string json)
{
if(json doesnt include __type)
{
if(json property type(my property) is MessageType.Text)
add to json "__type":"BusTextMessage:#TransportModels.Messages"
///etc
}
}
I Found this methods but it doesn't seem to be usable:
[OnDeserializing()]
internal void OnDeserializingMethod(StreamingContext context)
{
}
I think you need to add the KnownType attribute to the BusMessage class.
[DataContract]
[KnownType(typeof(BusTextMessage)]
public class BusMessage
{
.
.
.
}
This is the quickest solution I discovered. I configure MessageInspector and handle AfterReceiveRequest. Then I check message format(XML,JSON). If it is XML(for example sent from any WCF Client written in C#, WCF is configured to send everything with XML's) then I accept that message because field __type will be automatically inserted by WCF mechanism. Otherwise I Check if it is JSON, for example sent from external client. If it doesn't contain property "__type" I check my property Type and generate proper __type value. For example if my Type is equal to Text I add __type property BusTextMessage:#TransportModels.Messages and insert it into JSON and then recreate the message. I couldn't find quicker and easier solution and it seems to be working. Handling AfterReceiveRequest I found at http://code.msdn.microsoft.com/windowsdesktop/WCF-REST-Message-Inspector-c4b6790b.
public class MessageTypeInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
RecreateMessage(ref request);
return null;
}
}
private void RecreateMessage(ref Message message)
{
WebContentFormat messageFormat = this.GetMessageContentFormat(message);
var ms = new MemoryStream();
XmlDictionaryWriter writer = null;
switch (messageFormat)
{
case WebContentFormat.Default:
case WebContentFormat.Xml:
writer = XmlDictionaryWriter.CreateTextWriter(ms);
break;
case WebContentFormat.Json:
writer = JsonReaderWriterFactory.CreateJsonWriter(ms);
break;
case WebContentFormat.Raw:
this.ReadRawBody(ref message);
break;
}
message.WriteMessage(writer);
writer.Flush();
string messageBody = Encoding.UTF8.GetString(ms.ToArray());
if (messageFormat == WebContentFormat.Json && !messageBody.Contains("__type"))
messageBody = AddTypeField(messageBody);
ms.Position = 0;
ms = new MemoryStream(Encoding.UTF8.GetBytes(messageBody));
XmlDictionaryReader reader = messageFormat == WebContentFormat.Json ?
JsonReaderWriterFactory.CreateJsonReader(ms, XmlDictionaryReaderQuotas.Max) :
XmlDictionaryReader.CreateTextReader(ms, XmlDictionaryReaderQuotas.Max);
Message newMessage = Message.CreateMessage(reader, int.MaxValue, message.Version);
newMessage.Properties.CopyProperties(message.Properties);
message = newMessage;
}
private WebContentFormat GetMessageContentFormat(Message message)
{
WebContentFormat format = WebContentFormat.Default;
if (message.Properties.ContainsKey(WebBodyFormatMessageProperty.Name))
{
WebBodyFormatMessageProperty bodyFormat;
bodyFormat = (WebBodyFormatMessageProperty)message.Properties[WebBodyFormatMessageProperty.Name];
format = bodyFormat.Format;
}
return format;
}
private string AddTypeField(string jsonReply)
{
var typeRegex = new Regex("\"type\":(?<number>[0-9]*)");
Match match = typeRegex.Match(jsonReply);
if (match.Success)
{
int number = Int32.Parse(match.Groups["number"].Value);
var type = (MessageType)number;
var nameFormat = string.Format("Bus{0}Message", type);
string format = string.Format("\"__type\":\"{0}:#TransportModels.Messages\"", nameFormat);
jsonReply = "{" + string.Format("{0},{1}", format, jsonReply.Substring(1));
return jsonReply;
}
else
{
throw new Exception("Wrong message type.");
}
}
So I'm stuck at this point. I am trying to communicate with JanRain's "auth_info" service. In fact, to start, I'm just trying to get the "error" message/object/'.jsthingy' that you get when you surf to it directly in the browser:
https://rpxnow.com/api/v2/auth_info
but I want to get that back with a WCF call.
According to Fiddler, the content type of the information at that url is text/javascript. However, from what I can tell, WCF doesn't give me that option when calling it through WCF. I get two options: WebMessageFormat.Json, or WebMessageFormat.Xml.
I get the following error in Visual Studio:
InvalidOperationException was unhandled by User Code -
The incoming message has an unexpected message format 'Raw'. The expected message formats for the operation are 'Xml', 'Json'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details.
WTF? So can WCF even do this? (I suspect a more manual solution ahead)
JanRain's online code examples are a little bit lacking in the C# examples.
Their documentation link on auth_info is here https://rpxnow.com/docs#auth_info
The address of their auth_info service is here:
https://rpxnow.com/api/v2/auth_info
[TestMethod]
public void CallJanRain()
{
var x = new JanRainProxy("https://rpxnow.com/api/v2");
x.GetAuthInfo("", ""); //the params are apiKey, and token. not passing either at the moment as I want to be able to know how to at least handle the error first. After all, the *browser* at least got it..
}
[ServiceContract]
public interface IJanRainContract
{
[OperationContract(Name="auth_info")]
[WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Xml)]
JanRainAuthInfo GetAuthInfo(string apiKey, string token);
}
[DataContract]
public class JanRainAuthInfo
{
[DataMember(Name="identifier")]
public string Identifier { get; set; }
}
public class JanRainProxy: ClientBase<IJanRainContract>
{
public JanRainProxy(string url, WebHttpSecurityMode securityMode = WebHttpSecurityMode.Transport)
: base(ConstructEndpoint(url, securityMode))
{
}
//JanRainContract
public JanRainAuthInfo GetAuthInfo(string apiKey, string token)
{
return base.Channel.GetAuthInfo(apiKey, token);
}
// This method constructs a WebHttpBinding endpoint with all the appropriate
// settings for talking to our services.
private static ServiceEndpoint ConstructEndpoint(string serviceUri, WebHttpSecurityMode securityMode)
{
var contract = ContractDescription.GetContract(typeof(IJanRainContract));
var binding = new WebHttpBinding(securityMode);
//{
// MaxBufferPoolSize = 524288000,
// MaxReceivedMessageSize = 65536000
//};
var address = new EndpointAddress(serviceUri);
var endpoint = new ServiceEndpoint(
contract,
binding,
address);
var webHttpBehavior = new WebHttpBehavior()
{
DefaultBodyStyle = WebMessageBodyStyle.Wrapped,
DefaultOutgoingRequestFormat = WebMessageFormat.Json,
DefaultOutgoingResponseFormat = WebMessageFormat.Json,
AutomaticFormatSelectionEnabled = true,
FaultExceptionEnabled = true
};
endpoint.Behaviors.Add(webHttpBehavior);
return endpoint;
}
}
I'm figuring that perhaps I should leave the contenttype at json and tweak the behavior, or binding.
ok.. it looks like I needed to add a custom contentTypeMapper on my binding
after declaring my binding I added the following:
WebContentTypeMapper customMapper = new JsonContentTypeMapper();
binding.ContentTypeMapper = customMapper;
here's the custom Mapper:
public class JsonContentTypeMapper : WebContentTypeMapper
{
public override WebContentFormat
GetMessageFormatForContentType(string contentType)
{
if (contentType == "text/javascript")
{
return WebContentFormat.Raw;
}
else
{
return WebContentFormat.Json;
}
}
}
Kevin,
Here is a C# example on how to process the auth_info response that you might find helpful:
//C# Helper Class for Janrain Engage
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Xml;
using System.Xml.XPath;
public class Rpx
{
private string apiKey;
private string baseUrl;
public Rpx(string apiKey, string baseUrl) {
while (baseUrl.EndsWith("/"))
baseUrl = baseUrl.Substring(0, baseUrl.Length - 1);
this.apiKey = apiKey;
this.baseUrl = baseUrl;
}
public string getApiKey() { return apiKey; }
public string getBaseUrl() { return baseUrl; }
public XmlElement AuthInfo(string token) {
Dictionary<string,string> query = new Dictionary<string,string>();
query.Add("token", token);
return ApiCall("auth_info", query);
}
public List<string> Mappings(string primaryKey) {
Dictionary<string,string> query = new Dictionary<string,string>();
query.Add("primaryKey", primaryKey);
XmlElement rsp = ApiCall("mappings", query);
XmlElement oids = (XmlElement)rsp.FirstChild;
List<string> result = new List<string>();
for (int i = 0; i < oids.ChildNodes.Count; i++) {
result.Add(oids.ChildNodes[i].InnerText);
}
return result;
}
public Dictionary<string,ArrayList> AllMappings() {
Dictionary<string,string> query = new Dictionary<string,string>();
XmlElement rsp = ApiCall("all_mappings", query);
Dictionary<string,ArrayList> result = new Dictionary<string,ArrayList>();
XPathNavigator nav = rsp.CreateNavigator();
XPathNodeIterator mappings = (XPathNodeIterator) nav.Evaluate("/rsp/mappings/mapping");
foreach (XPathNavigator m in mappings) {
string remote_key = GetContents("./primaryKey/text()", m);
XPathNodeIterator ident_nodes = (XPathNodeIterator) m.Evaluate("./identifiers/identifier");
ArrayList identifiers = new ArrayList();
foreach (XPathNavigator i in ident_nodes) {
identifiers.Add(i.ToString());
}
result.Add(remote_key, identifiers);
}
return result;
}
private string GetContents(string xpath_expr, XPathNavigator nav) {
XPathNodeIterator rk_nodes = (XPathNodeIterator) nav.Evaluate(xpath_expr);
while (rk_nodes.MoveNext()) {
return rk_nodes.Current.ToString();
}
return null;
}
public void Map(string identifier, string primaryKey) {
Dictionary<string,string> query = new Dictionary<string,string>();
query.Add("identifier", identifier);
query.Add("primaryKey", primaryKey);
ApiCall("map", query);
}
public void Unmap(string identifier, string primaryKey) {
Dictionary<string,string> query = new Dictionary<string,string>();
query.Add("identifier", identifier);
query.Add("primaryKey", primaryKey);
ApiCall("unmap", query);
}
private XmlElement ApiCall(string methodName, Dictionary<string,string> partialQuery) {
Dictionary<string,string> query = new Dictionary<string,string>(partialQuery);
query.Add("format", "xml");
query.Add("apiKey", apiKey);
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<string, string> e in query) {
if (sb.Length > 0) {
sb.Append('&');
}
sb.Append(System.Web.HttpUtility.UrlEncode(e.Key, Encoding.UTF8));
sb.Append('=');
sb.Append(HttpUtility.UrlEncode(e.Value, Encoding.UTF8));
}
string data = sb.ToString();
Uri url = new Uri(baseUrl + "/api/v2/" + methodName);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
// Write the request
StreamWriter stOut = new StreamWriter(request.GetRequestStream(),
Encoding.ASCII);
stOut.Write(data);
stOut.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream dataStream = response.GetResponseStream ();
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = false;
doc.Load(dataStream);
XmlElement resp = doc.DocumentElement;
if (resp == null || !resp.GetAttribute("stat").Equals("ok")) {
throw new Exception("Unexpected API error");
}
return resp;
}
public static void Main(string[] args) {
Rpx r = new Rpx(args[0], args[1]);
if (args[2].Equals("mappings")) {
Console.WriteLine("Mappings for " + args[3] + ":");
foreach(string s in r.Mappings(args[3])) {
Console.WriteLine(s);
}
}
if (args[2].Equals("all_mappings")) {
Console.WriteLine("All mappings:");
foreach (KeyValuePair<string, ArrayList> pair in r.AllMappings()) {
Console.WriteLine(pair.Key + ":");
foreach (string identifier in pair.Value) {
Console.WriteLine(" " + identifier);
}
}
}
if (args[2].Equals("map")) {
Console.WriteLine(args[3] + " mapped to " + args[4]);
r.Map(args[3], args[4]);
}
if (args[2].Equals("unmap")) {
Console.WriteLine(args[3] + " unmapped from " + args[4]);
r.Unmap(args[3], args[4]);
}
}
}
Code source: https://github.com/janrain/Janrain-Sample-Code/blob/master/c-sharp/csharp-helper-class.cs