I have a WCF service that I'm using for calling a C# function via URL, this is the code that I use for the url:
[WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Xml,
ResponseFormat = WebMessageFormat.Xml, UriTemplate = "?GetValuesVar={Var}")]
string getHisUmsTimeRedVar(string Var);
Once donde that I'm using the parameters of the URL for calling a function and to retrieve a value. My problem is that all the XML code is between <string></string> tags.
<string>
<?xml version="1.0"?><ArrayOfHistoricVal
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<HistoricVal>
<Date>2016-05-31T22:00:00</Date><Value>2060</Value>
</HistoricVal>
</ArrayOfHistoricVal>
</string>
Is there a way to retrieve this values as a normal XML instead of between those two <string></string> tags?
Edit: The values to get are in a function like this one:
public string getHisUmsTimeRedVar(string idVar)
{
try
{
ADAMUtil.Log.info("getHisUmsTimeRed. Empieza = ");
DateTime FechaIni = new DateTime(2015, 05, 05, 0, 0, 0);
DateTime FechaFin = new DateTime(2018, 05, 05, 0, 0, 0);
List<HistoricVal> list = new List<HistoricVal>();
List<His> Historicos = null;
ADAMUtil.Log.info("getHisUmsTimeRed. Empieza1 = ");
Historicos = getHisUmsTimeRed("admin", "admin", Convert.ToInt64(idVar), 14, null, 0, 0, FechaIni, FechaFin, 0, "Romance Standard Time");
ADAMUtil.Log.info("getHisUmsTimeRed. Historicos = " + Historicos.Count);
for (int i = 0; i < Historicos.Count; i++)
{
HistoricVal item = new HistoricVal();
item.Date = Historicos[i].IniDat;
item.Value = Historicos[i].Val;
list.Add(item);
}
String xmlDoc;
xmlDoc = toXML.VartoXML(list);
//Browser.BrowserOpen();
return xmlDoc;
}
catch (Exception ex)
{
ADAMUtil.Log.info("getHisUmsTimeRed. ex = " + ex.ToString() + ex.StackTrace.ToString());
return null;
}
}
And the webinvoke must be an Stream, not a string.
[WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Xml,
ResponseFormat = WebMessageFormat.Xml, UriTemplate = "?GetValuesVar={Var}")]
stream getHisUmsTimeRedVar(string Var);
The problem with your XML string is that it is erroneous XML: the XML declaration should be at the very start.
You can't easily convert it to a XElement or XDocument like this.
There are thus two solutions:
Change your method so that it doesn't return a string, but a XElement in the first place.
Work with your string yourself to remove the additional tags. This solution is not robust to change or edges cases, and I recommend you use the first one. But if you are unable to change the called method, this will at least help you out :
//Trims 8 characters (<string>) at the beginning and 9 at the end.
String correctString = yourString.Substring(8, yourString.Length - 17);
EDIT: After discussing the issue in the comments, it seemed that only the browser displayed the <string> tags, and they were not present in the XML file. This was due to it serializing your string object, most likely.
By either serializing it yourself and passing this to your browser with XElement.Parse() or changing the type of your object directly, the browser was able to understand what it was supposed to display.
Change
public string getHisUmsTimeRedVar
To
public XDocument getHisUmsTimeRedVar
to return proper xml not involved in a string tag.
Related
I Create a simple WCF service and he works fine.
The configuration are below
The interface have this configuration
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "checkSymbolExistJson/{pSymbol}")]
string checkSymbolExistJson(string pSymbol);
The implementation is this
public string checkSymbolExistJson(string pSymbol)
{
Person p = new Person();
p.name = pSymbol;
p.age = 15;
string json = JsonConvert.SerializeObject(p);
return json;
}
if I enter URL in browser "http://localhost/MetaTraderWcf/rzManageQuotes.svc/checkSymbolExistJson/testename" in brower I Get this result in Browser
"{\"name\":\"testename\",\"age\":15}"
After I make a win 32 application to get http result of this WCF service.
I use this code to read a HTML page
public string readUrl(string pUrl)
{
WebClient client = new WebClient { Encoding = System.Text.Encoding.UTF8 };
return client.DownloadString(pUrl);
}
I use this code to read a JSON dinamic TAG
private void button2_Click(object sender, EventArgs e)
{
string tmpToken = readUrl(url.Text);
// string tmpToken = "{\"name\":\"testename\",\"age\":15}";
JToken token = JObject.Parse(tmpToken);
string page = (string)token.SelectToken("name");
jSONResult.Text = page;
}
if I Runing code above with fixed code below
string tmpToken = "{\"name\":\"testename\",\"age\":15}";
The result is correct and I get result as "testename".
But when I Debug the read a Html page I receive tha value of tmpToken with this string
"\"{\\"name\\":\\"testename\\",\\"age\\":15}\""
And I get a error when I read dinamic value of name
An unhandled exception of type 'Newtonsoft.Json.JsonReaderException' occurred in Newtonsoft.Json.dll
Additional information: Error reading JObject from JsonReader. Current
JsonReader item is not an object: String. Path '', line 1, position
37.
If I change interface to return a XML page like this code
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Xml,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "checkSymbolExistJson/{pSymbol}")]
string checkSymbolExistJson(string pSymbol);
I get the follow result in browser
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">{"name":"testename","age":15}</string>
And I get Read JSON value of name correct after remove tag from XML result.
The Question is
There is some way of read a string in pure JSON format in c# like a read in a Browser format
like this
{"name":"testename","age":15}
and not like this format
"\"{\\"name\\":\\"testename\\",\\"age\\":15}\""
there is a simple solution for that. just return stream except string.
public stream checkSymbolExistJson(string pSymbol)
{
Person p = new Person();
p.name = pSymbol;
p.age = 15;
string json = JsonConvert.SerializeObject(p);
return new MemoryStream(Encoding.UTF8.GetBytes(json));
}
or i suggest use web API instead WCF.
I'm writing a web service as code below:
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json,
// BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "/BudgetBalance/{userlogin}/{prnumber=null}")]
Budget BudgetBalance(string userlogin, string prnumber);
As you can see at the code above, the second parameter can be filled or keeped null. By doing this, I can access the service by two different urls.
http://localhost:44880/Service1.svc/BudgetBalance/nurul.widiyanti
http://localhost:44880/Service1.svc/BudgetBalance/nurul.widiyanti/PRM-000114
If the second parameter is filled with some data, the service will return a different value. The problem is when I want to consume this webservice. Here's the code I've tried to call this service.
WebClient proxy = new WebClient();
string serviceUrl = string.Format("http://localhost:1089/Service1.svc/BudgetBalance/Nurul.Widiyanti/PRM-000114");
byte[] data = proxy.DownloadData(serviceUrl);
Stream _mem = new MemoryStream(data);
var reader = new StreamReader(_mem);
var result = reader.ReadToEnd();
var model = JsonConvert.DeserializeObject<Budget>(result);
This doesn't work and make an error. I realize that this code will work if I change the UriTemplate within OperationContract to something like this:
UriTemplate = "/BudgetBalance/{userlogin}/{prnumber}"
But if I do this, it doesn't suit my requirement. I need to create a webservice which allow one of the parameters remains empty (null). Is this possible accomplish this requirement? If so, please guide me to find the answer.
I think you want something like this ...
...
UriTemplate = "/BudgetBalance/{userlogin}")]
UriTemplate = "/BudgetBalance/{userlogin}/{prnumber}")]
Budget BudgetBalance(string userlogin, string prnumber = null) { .. }
I use WCF (by means of using the WebChannelFactory) to invoke some services that are outside of my control, implemented in a variety of technologies. From the WCF perspective, my interface only has one method, let's call it "get-stuff". So, the same method can be implemented by these services as http://www.service-a.com/get-stuff, or as http://www.service-b.com/my-goodies/, or as http://www.service-c.com/retrieve-thing.php
In all examples I've seen the method binding to a particular URI is accomplished via the UriTemplate member of the WebGet/WebInvoke attribute. But this means, all the URIs for the "get-stuff" method must follow a fixed template. For, example, I can create a UriTemplate = "/get-stuff", so that my method will always be bound to /get-stuff.
However, I want my method to bind to any arbitrary URI. BTW, the parameters are passed as a POST data, so I do not need to worry about binding URI to parameters of the method.
why don't you do something like this
EndpointAddress endpointAddress = new EndpointAddress("any service url");
ChannelFactory<IMyService> channelFactory = new ChannelFactory<IMyService>(binding, endpointAddress);
IMyServiceclient = channelFactory.CreateChannel();
client.GetStuff();
OK, I have found a solution to the problem, by patching the UriTemplate of the WebInvokeAttribute at run-time. My single-method WCF interface is:
[ServiceContract]
interface IGetStuff
{
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
ResponseData GetStuff(RequestData request);
}
Here is how I get the handle to the interface:
//Find the last portion of the URI path
var afterLastPathSepPos = uri.LastIndexOf('/', uri.Length - 2) + 1;
var contractDesc = ContractDescription.GetContract(typeof(IGetStuff));
foreach (var b in contractDesc.Operations[0].Behaviors)
{
var webInvokeAttr = b as WebInvokeAttribute;
if (webInvokeAttr != null)
{
//Patch the URI template to use the last portion of the path
webInvokeAttr.UriTemplate = uri.Substring(afterLastPathSepPos, uri.Length - afterLastPathSepPos);
break;
}
}
var endPoint = new ServiceEndpoint(contractDesc, new WebHttpBinding(), new EndpointAddress(uri.Substring(0, afterLastPathSepPos)));
using (var wcf = new WebChannelFactory<I>(endPoint))
{
var intf = wcf.CreateChannel();
var result = intf.GetStuff(new RequestData(/*Fill the request data here*/)); //Voila!
}
I'm hosting a service and trying to pass it a url as a parameter ... I know I've got to encode the url - but when I put a break point inside my method it only gets hit if I pass certain encodings - not others such a forward slash ...
So ...
http://myurl.com:8181/blah
works fine - even something like (encoded colon) ...
http://myurl.com:8181/blah%3A
but if I try to pass an encoded slash
http://myurl.com:8181/blah%2F
I get 'Endpoint not found' and my breakpoint isn't hit ...
Can anyone assist please?
Code below ...
Hosting the service ...
var instantPrintService = new WebServiceHost(typeof(InstantPrintService), new Uri("http://myurl:8181/"));
instantPrintService.Open();
The interface ....
[ServiceContract]
public interface IInstantPrint
{
[OperationContract]
[WebGet(UriTemplate = "printlabel/{filepath}", ResponseFormat = WebMessageFormat.Json )]
Response PrintLabel(string filepath);
}
The print label method ...
public Response PrintLabel(string filepath)
{
try
{
return new Response { Success = true, Message = "Success" };
}
catch (Exception ex)
{
return new Response { Success = false, Message = ex.ToString() };
}
}
So I'm a complete noob with C# and web stuff and trying to figure something out. There is some code that says this:
[WebInvoke(UriTemplate = "People", Method = "GET", ResponseFormat = WebMessageFormat.Json)]
public string GetPeople() {
Person results = DataAccess.ParsePeople();
System.WebScrip.Serialization.JavaScriptSerializer oSerializer = oSerializer.MaxJsonLength = int.MaxValue;
string sJSON = oSerializer.Serialize(results);
return sJSON;
}
When I type in the url for this method, my response looks like:
"{\"AddressesCollection\":[{\"Street\":\"1234 Temp Dr\",\"Zip\":94011},{\"Street\":\"56789 Nothing Dr\",\"Zip\":2222},\"ErrorMessage\":\"SUCCESS\"}"
I was trying to follow this tutorial on the iPad side: http://www.raywenderlich.com/5492/working-with-json-in-ios-5
Looking at the website they used as an example, the JSON output looks like:
{"paging":{"page":1,"total":4440,"page_size":20,"pages":222},"loans":[{"id":447290,"name":"Rosa","description":{"languages":["es","en"]},"status":"fundraising","funded_amount":0,"basket_amount":0,"image":{"id":1134583,"template_id":1},"activity":"Animal Sales","sector":"Agriculture","use":"to buy barnyard fowl and feed.","location":{"country_code":"PE","country":"Peru","town":"M\u00f3rrope - Lambayeque","geo":{"level":"country","pairs":"-10 -76","type":"point"}},"partner_id":143,"posted_date":"2012-07-13T19:00:05Z","planned_expiration_date":"2012-08-12T19:00:05Z","loan_amount":400,"borrower_count":1},{"id":447292,"na
On the iPad, when I do:
NSDictionary *fields = [NSJSONSerialization JSONObjectWithData:response options:kNilOptions error:&error];
or
NSArray *fields = [NSJSONSerialization JSONObjectWithData:response options:kNilOptions error:&error];
both are empty. Is it the output of the C# that is not proper JSON? Thanks.
Your JSON string is missing a closing ] somewhere.
Assuming the string you posted is exactly what was returned by the server, you will also probably need to remove the backslashes in order to make it valid JSON.
NSString *responseString = [[[NSString alloc] initWithData:response] stringByReplacingOccurrencesOfString:#"\\" withString:#""];
NSDictionary *fields = [NSJSONSerialization JSONObjectWithData:responseString options:kNilOptions error:&error];