How to call a web service using XDocument? - c#

Suppose I have an asmx web service at the following address:
http://localhost/BudgetWeb/Service.asmx
This web service has a web method with the following signature:
string GetValue(string key)
This GetValue method returns a string like this:
<?xml version=\"1.0\" encoding=\"utf-8\" ?><value>250.00</value>
What if I wanted to do this:
XDocument doc = XDocument.Load("http://localhost/BudgetWeb/Service.asmx?op=GetValue&key=key1")
This doesn't work, and I'm pretty sure that XDocument.Load doesn't actually invoke a web method on the server. I think it expects the uri to point to a file that it can load. To call a web method, I think I'd have to have a web proxy class and would have to use that to call string GetValue(string key), and then I could use that value returned from the web proxy class to pass to the XDocument.Load method.
Is my understanding correct, or is there a way for XDocument.Load to actually invoke a web method on the server?

Try to use this:
XDocument doc = XDocument.Load(
"http://localhost/BudgetWeb/Service.asmx/GetValue?key=key1");
EDIT: Just figured out: you're using a invalid URI:
http://localhost/BudgetWeb/Service.asmx?op=GetValue&key=key1
Should be
http://localhost/BudgetWeb/Service.asmx/GetValue?key=key1
I'm using this code snippet:
string uri = "http://www.webservicex.net/stockquote.asmx/GetQuote?symbol=MSFT";
XDocument doc1 = XDocument.Load(uri);
Console.WriteLine(doc1.Root.Value); // <StockQuotes><Stock><Symbol>MSFT...

Ok, I found the issue. In the web.config for the web service, you have to add this:
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
Thanks to everyone for their suggestions, I really appreciate it, especially Rubens Farias whose working example put me on the right track.

Related

how to handle parameter with space and slash in uri C# WEB API 2

I have an controller called Test Controller and the method name is Test
The Test Method accepts one parameter. But when the parameter contains value having space slash the web api is giving error. I am using WEB API 2.
[Route("Test/{companyName}")]
[AcceptVerbs("GET", "POST")]
[System.Web.HHttpGet]
public HttpResponseMessage Test(string companyName)
{
}
the parameter value is BTL / Force Motor Ltd.
I have tried but nothing happened.
<uri>
<schemeSettings>
<add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
</schemeSettings>
</uri>
You need to URL Encode the values you are sending to your API, like this:
http://yourApiDomainName/api/yourControllerName/?companyName=BTL%20%2F%20Force%20Motor%20Ltd
[SPACE] when URL encoded beomes: %20
[Forward Slash] when URL encoded becomes: %2F
you dont need to http decode the values in your controller, as these values will be decoded by the framework as soon as they reach your controller. So you will see 'BTL%20%2F%20Force%20Motor%20Ltd' as 'BTL / Force Motor Ltd' inside your controller.
for full list of URL Encodings see this:
http://www.w3schools.com/tags/ref_urlencode.asp
Your issue has nothing to do with WebAPI itself but how ASP.Net handles some specific Urls. This may also affect any dots (".") that get passed in to your API. Here's what worked for me:
Add this line to your web.config under system.web
<httpRuntime relaxedUrlToFileSystemMapping="true" />
Phil Haacked has a great article that goes into more detail.

Post request body too large (string in parameter object too large)

I have an MVC method:
public void PushFile([FromBody]FileTransport fileData)
Class is:
public class FileTransport
{
public string fileData;
}
In fileData I put byte[] from a file converted into a string (UTF-8), so the string can be large.
Problem is: if the string is too large (somewhere above 15000 characters) the fileData parameter is null. If the string is not that large, everything works fine and the parameter is as it should be.
How can I allow MVC to accept larger strings, or do I need to compress the string somehow beforehand?
EDIT:
Already tried:
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="2147483644"/>
</webServices>
</scripting>
</system.web.extensions>
But does not work. Maybe because MVC uses JSON.NET instead of the normal JsonSerializer?
Did you try to increase max length of the request?
<system.web>
<httpRuntime maxRequestLength="{REQUEST_LENGTH}"/>
<system.web>
Simple Point is - you dont put the string into the URL. Simple like that. Add it as payload. URL's are ressource locators, not "Content carriers".
I figured out it had nothing to do with content length. If seems like the Json does not encode properly with some characters on the sender's side, that's when MVC controller recieved null.

How to consume web service via GET methods?

I have a normal 3rd party SOAP service with WSDL and stuff. The problem is - it only accepts GET requests. How can I access it in c#?
When I add that service to VS via Add Service Reference and try to use it as usual:
var service = new BaseSvcClient(
new BasicHttpContextBinding(),
new EndpointAddress("http://some.internal.ip/WebServices/Base.svc"));
var ver = service.Version();
I see (via fiddler) that it actually sends POST requests and web-service responds with Endpoint not found error message.
If I simply hit http://some.internal.ip/WebServices/Base.svc/Version in a browser the proper xml is returned.
I can use WebClient, but then I have to construct all the GET requests manually, which doesn't look good.
Are there other solutions?
I have found an answer that helped me a lot.
Basically if I take an autogenerated interface for the client, decorate methods with [WebGet] and use
var cf = new WebChannelFactory<IBaseSvc2>(new Uri("..."));
var service = cf.CreateChannel();
var result = service.Version();
it all works well. That's not a perfect solution, since changes won't be picked up automatically, so may be there are other solutions?
P.S. an interface for a web service is now like:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName = "BaseService.IBaseSvc")]
public interface IBaseSvc2
{
[System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IBaseSvc/Version", ReplyAction = "http://tempuri.org/IBaseSvc/VersionResponse")]
[WebGet]
VersionInformation Version();
}
You can achieve it by adding the protocols in config file
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>

Creating a custom .svc handler for WCF service hosted in IIS

I am hosting a wcf service in IIS 7. I was curious if it would be possible to create my own .svc HttpHandler mapping and class to handle service requests.
For example, if I was to intercept any requests to files that ended with an extension of ".foo" I could add this to my web.config
<handlers>
<add name="*.foo_**" path="*.foo" verb="*" type="MyServer.FooHttpHandler" />
</handlers>
And I could have a class in my default root that did the following
public class FooHandler: IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
// do stuff, validate?
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("filename={0}", url));
HttpContext.Current.Response.AddHeader("Content-Type", "fooMimeType");
HttpContext.Current.Response.WriteFile(url);
HttpContext.Current.Response.End();
}
public bool IsReusable
{
get { return false; }
}
}
Is it possible to do something like this with wcf .svc requests? I'm not sure if it'd be the exact same thing or not, since I'm not necessary serving a file to respond with, I want to intercept and proxy the response.
Or is a better way to implement a service behavior that does my required pre-service logic?
What are you trying to achieve? Not sure if you can replace the existing *.svc http handler - but what you can do much more easily is create your own custom ServiceHostFactory for the WCF service. You basically add one attribute your *.svc file:
<%# ServiceHost Language="C#" Debug="true"
Service="YourNamespace.YourService"
Factory="YourNamespace2.YourServiceHostFactory" %>
Using this, IIS will now instantiate your own YourServiceHostFactory and ask you to create an instance of the YourService class. Maybe you can hook into the flow here and do what you need to do?
You could use ASP.NET Routing and an IRouteHandler that returns your own IHttpHandler implementation as well if you really want to as well
http://msdn.microsoft.com/en-us/library/system.web.routing.iroutehandler.gethttphandler.aspx
http://msdn.microsoft.com/en-us/library/cc668201.aspx
I've done this in the past when setting up WCF Data Services and I don't see why it can't work here as well.

Output (server-side) caching of ashx files

I am trying to enable output caching on all ashx files in my site. I'm trying to keep the server from generating the file on each request - NOT trying to tell the browser to cache the file.
I've distilled my ashx file down to this simple code:
public class DefaultStyles : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/css";
StringBuilder styleSheet = new StringBuilder();
styleSheet.AppendLine(string.Format("/* Generated: {0}, {1} */", DateTime.Now.ToShortDateString(), DateTime.Now.ToLongTimeString()));
context.Response.Write(styleSheet.ToString());
}
}
And in my web.config file, i have this:
<system.webserver>
<caching enabled="true">
<profiles>
<add extension=".ashx" policy="CacheForTimePeriod" duration="00:01:00" />
</profiles>
</caching>
</system.webserver>
Still, every request i make to the ashx file generates a new version with the current date and time in it.
What am i doing wrong?
Thanks.
Maybe this will help?
http://objectmix.com/dotnet/393333-output-caching-custom-http-handler.html
It would seem to suggest that since you're not using the normal page handler, the output caching module isn't invoked.
Simon
I was actually doing everything right, just not testing in the right environment. Once i deployed the simple example above on our IIS 7 server, it worked as expected with the code above. It should be noted that this DID NOT work on our IIS 6 server. I had not realized that this was a new feature only available in IIS 7

Categories

Resources