WebApi and Ampersands in name - angularjs

So my angular website has a webapi with the following method.
[Route("items/{itemName}")]
public object GetMcguffinsByItem(string itemName)
{
return _mcguffinsService.GetAllByItemName(itemName);
}
However, an item name can have an ampersand as a valid character. However when attempting to use items that do have an ampersand, the method will return a 400 badrequest.
Im not sure how to go about fixing this problem.
For more verification: I was under the impression that encoding and using %26 is all required to pass an ampersand to part of the URI. It seems to be a common answer when searching my problem. I have excluded the angular as I can verify that it builds the string correctly, and other names produce the desired result.
The javascript method encodeURIComponent() followed by using the angular service double encodes the item name, and returns a 404.
EDIT:
Sample Input:
A&B 266
After Encoding:
A%26B%20266
Console:
angular.js:10722 GET http://localhost:60894/api/v1/mcguffins/items/A%26B%20266 404 (Not Found)
Using the browser on api directly with same input gives this error:
[HttpException (0x80004005): A potentially dangerous Request.Path value was detected from the client (&).]
System.Web.HttpRequest.ValidateInputIfRequiredByConfig() +11944671
System.Web.PipelineStepManager.ValidateHelper(HttpContext context) +55

Related

Several GET Methods in ASP .NET WEB API causing 500 when sending array using URI

In my ASP .NET WEB API, I want to use the following methods:
[Route(""), HttpGet]
public IDictionary<int, string> GetAll()
{
//doSth
}
[Route(""), HttpGet]
public IDictionary<int, string> GetSpecificOnes([FromUri]IEnumerable<int> carsIds)
{
//doSth
}
When requesting the second one using angular, I get the following exception:
angular.js:12011 GET http://localhost:12345/_api/cars?&carsIds[0]=1&carsIds[1]=2&carsIds[2]=5 500 (Internal Server Error)
I think the problem is, that I have two GET-Methods without a route. But I don't need one. How do I solve this problem?
You actually don't need to define a route, like you say, as long as the GET methods in the controllers have different signatures and parameterlist.
The problem in your case is that you call the method the wrong way.
Either change the parameter name in the api method to carsIds or change the angular HTTP query string to ?ids[0]=1&ids[1]=2&ids[2]=5

How do you append a url as a query param value

My website has a search form where someone can search a URL beginning with http:// like this:
https://www.google.com
which should then be encoded and appended as a query parameter value like this:
localhost:4000/api/https%3A%2F%2Fwww.google.com
When I run it (above) locally, it works, but when deployed (below):
https://api.mysite.com/search/api/https%3A%2F%2Fwww.google.com%2F
=> returns 404.
If I type this in:
http://localhost:4000/api/https://www.google.com
I get this error:
Phoenix.Router.NoRouteError at GET /api/v1/https://www.google.com
no route found for GET /api/v1/https:/www.google.com (ExternalPing.Router)
I'm not sure if these are related. What is the correct way to append a url as a query parameter value?
I have already tried encoding with URI.encode and URI.encode_www_form but they didn't resolve this
Now you haven't posted your server code, so I am just going to assume here.
I think the problem is that you didn't encode the second string, since it contains / in the url you have problems.
The url is:
http://localhost:4000/api/https://www.google.com
The server will interpret it wrong. So you are asking for a route called:
/api/https:/
With a parameter called /www.google.com
You need to encode the query string.
But again this is guessing since I have no idea how your server looks.
I just tried calling an endpoint at my iis server with a unencoded url as a parameter, and this is what it gave me back:
<Error>
<Message>The request is invalid.</Message>
</Error>

Web api is giving error on passing * as the input value to the api method parameter

I am using asp.net mvc web api and i have this method
[HttpGet]
public LoginResult AuthenticateOnlineBookingUser(String userName,String password)
{
//My Code
}
The problem is that when i pass (*) as input value to the parameter (password)
i receieve this error but on other inputs it is working perfectly
A potentialy dangerous Request.Path.value was detected from client(*)
Thanks in advance
Note:My client side is written in angular js
i tried this solution as well Getting "A potentially dangerous Request.Path value was detected from the client (&)" but it is not working for me
You need to set the options for invalid characters. You can do this in your web.config as shown here.
Use url encoder to encode the request before sending it to server.
Finally solved my problem by changing my GET request to POST request The problem was with query string in Order to solve it with GET Request i have to make some changes to my query string in order to make it work but

Colons not being URL encoded in resource parameters

I'm using Angular's Resource module to access a web API, but I'm having problems as the API uses URIs as the primary key.
Whenever I try to make a call to this API, passing in a URI as a string parameter, I'm getting 400 Bad Request errors. On closer inspection, Resource is escaping all the forward slashes in the URI but not the colon at the start. It's doing a GET on a URL that looks like this: http://myserver/api/objects/http:%2F%2Fexample.comk%2FmyURI%2F, which is of course invalid. I've also tried escaping the colon with a backslash, but that doesn't work either.
How can I make Resource escape my parameters properly? I've tried replacing the colon with %3A before making the call, but that results in the % being encoded again, returning 404 Not Found.
The service handling Resource looks like this:
angular.module('adminApp').factory('MyObject', myObject);
function myObject($resource) {
return $resource('/api/objects/:uri');
};
and I'm calling it like this:
MyObject.get({ uri: myUri }, function(result) {
...
});
I've got around this issue by passing the URI as a query parameter instead of as part of the request URL. I did this by changing my resource service to this:
angular.module('adminApp').factory('MyObject', myObject);
function myObject($resource) {
return $resource('/api/objects');
};
and leaving the calling code this the same. ngResource then creates a GET that looks like http://myserver/api/objects?uri=http:%2F%2Fexample.comk%2FmyURI%2F, which is fine.
Basically, if you're using unusual characters in your API parameters, put them in a query string rather than in the URL! :-)

CXF wsdl2java, GZip compression, and stub reutilization

I´m using CXF to consume a WebService and, as the responses are quite large, I´m requesting with a gzip "Accept-Encoding" and using GZIPInInterceptor to handle the gziped response. Also my WSDL is very large (360kb) and it takes a long time(+10 seconds) to create the stub, because it has to read and parse the WSDL, so I´m creating the stub once and reusing it.
The problem is, whenever I try to use two different methods the second request gives me an error saying it is expecting the previous request.
To illustrate my problem I created a simple example with this public WebService:
http://www.webservicex.net/BibleWebservice.asmx?WSDL
Without the GZip compression it works fine:
BibleWebserviceSoap bibleService = new BibleWebservice().getBibleWebserviceSoap();
String title = bibleService.getBookTitles();
response.getWriter().write(title);
String johnResponse = bibleService.getBibleWordsbyKeyWord("John");
response.getWriter().write(johnResponse);
I´m able to receive both responses.
Enabling Gzip compression:
BibleWebserviceSoap bibleService = new BibleWebservice().getBibleWebserviceSoap();
//GZIP compression on bibleService
Client client = ClientProxy.getClient(bibleService);
client.getInInterceptors().add(new GZIPInInterceptor());
client.getInFaultInterceptors().add(new GZIPInInterceptor());
// Creating HTTP headers
Map<String, List<String>> headers = new HashMap<String, List<String>>();
headers.put("Accept-Encoding", Arrays.asList("gzip"));
// Add HTTP headers to the web service request
client.getRequestContext().put(Message.PROTOCOL_HEADERS, headers);
String title = bibleService.getBookTitles();
response.getWriter().write(title);
String johnResponse = bibleService.getBibleWordsbyKeyWord("John");
response.getWriter().write(johnResponse);
When I try to receive the second response I´m getting this exception:
org.apache.cxf.interceptor.Fault: Unexpected wrapper element {http://www.webserviceX.NET}GetBookTitlesResponse found. Expected {http://www.webserviceX.NET}GetBibleWordsbyKeyWordResponse.
On my real application I´m getting an exception with the request:
org.apache.cxf.binding.soap.SoapFault: OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name 'GetAvailabilityRequest' and namespace 'http://schemas.navitaire.com/WebServices/ServiceContracts/BookingService'. Found node type 'Element' with name 'ns4:PriceItineraryRequest' and namespace 'http://schemas.navitaire.com/WebServices/ServiceContracts/BookingService'
My sample project can be downloaded here:
http://www.sendspace.com/file/plt0m4
Thank you
Instead of setting the protocol headers directly like that, use CXF's GZIPOutInterceptor to handle that.
Either that or reset the PROTOCOL headers for each request. When set like that, the headers map gets updated as the request goes through the chain. In this case, the soapaction gets set. This then gets resent on the second request.

Resources