I have a WCF REST-service that is used by a mobile application used in different countries. It's accepting and returning JSON, and I use StructureMap.
The idea is to create one service instance for all countries, but I need to know what country is calling the service and do some logic on that in the service (for example, determine the connection string to be used).
however, I want to avoid that country code has to be passed with each service request. What are my options here?
Can I, for example, have one endpoint for each country? But in that case, how can I know what endpoint/country code was used to call the service?
Maybe other possibilities?
Multiple endpoints could be a solution, but you need a reliant way of determining which endpoint was actually used. Given the "disconnected" nature of WCF REST services (by that I mean the usage of non WCF types to do the communication and just using the WCF attributes), this would require you to write a WebHostFactory that specifies the country on creation of the service for a given endpoint. What you could to is inspect the WebOperationCurrent.Current instance to get access to information hidden from your method signature. For example:
Uri requestRoot = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.BaseUri;
if (requestRoot.PathAndQuery.Contains("en-us")) {
// use english locale
}
else if (requestRoot.PathAndQuery.Contains("de-de")) {
// use german locale
}
You would need a better strategy to determine the actual country/language, but the basic idea is to re-host the same service under multiple paths and inspect those paths within the request using the current WebOperationContext instance.
Edit
From the comments above, I would like to add that you have access to the UserAgent string for the current request using the WebOperationContext. So you could also inspect those information looking for a clue about the requested language. But keep in mind that those "implicit" information are only clues but never clear indications about what the user wants.
Related
I have one API and two different domain. How can I check which domain host triggered api request?
Example:
API: example.API.com
Domain1: example.Domain1.com
Domain2: example.Domain2.com
and I want to know which domain call my API?
I used C# for my code, maybe there is a ready way to solve my problem but if not then maybe some advice on how to approach the problem?
I try code.
string host = _httpContextAccessor.HttpContext?.Request.Headers.Referer.FirstOrDefault();
This code gives me the full url of the client, but I don't know if that's a good way because
this can be null.
I'm developing a REST API for managing company cars, where employees take cars, and go on rides.
Rides have a property called isActive.
When they finish a ride, the isActive property needs to be set to false.
How my API currently works is that the endpoint for finishing (
PATCH HTTP request) the rides is /api/v1/rides.
The user sends the PATCH request with the JWT token, and the API determines from the HTTP context which user it is, finds the individual ride associated with the user, updates the isActive property to false, and updates a short comment of type string that the user inputs.
Is this acceptable?
Every source that I found states that the endpoint should look something like /api/v1/rides/{rideId}, but I don't understand why it would be necessary in this context, because it would require more work on the front-end side.
Is this acceptable?
Probably not
PATCH /api/v1/rides
is a request to change the /api/v1/rides resource; which is to say the same resource that you are asking for when you send a GET /api/v1/rides request. If you are intending to modify some other resource instead, then the resource you intend to modify should be the target URI.
The potential problem is this: general purpose HTTP components think all resources understand requests the same way. This is the REST "self descriptive messages" interface constraint at work. When you advertise that your resource supports PATCH, my third party browser/spider/cache/proxy is allowed to assume that PATCH means the same thing for your resource that it does for every other resource on the web.
When something goes expensively wrong because your resource was using different semantics from what is standard, that's on you, not the client.
PATCH means "apply these changes to the resource identified by the target URI". If you are intending the edits to be applied to some other resource, then you should be specifying that identifier instead.
If you are doing something non-standard, then you should probably use POST, rather than PATCH, as the method token in the request. See Fielding 2009:
POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.”
I am new to WCF services and currently testing out things.
I have got a little REST API, which has several methods. Some of them require a user context (session), some others don't. At login, each user gets a session token. The client should supply this token and his user ID on every request via HTTP headers.
At the moment, I wrote a method for getting those two headers and validate the session, calling it on every method which will need a user context. This seems kinda nasty if the API gets bigger.
Is there a better approach for doing this?
You can leverage of following solutions:
Custom class deriving IClientMessageInspector/IDispatchMessageInspector for client and service respectively. Then you add its instance to MessageInspectors. Advantage of having messageInspector is that it's applied to single endpoint so regardless of having many endpoints exposed (both SOAP and REST), messageInspector can be associated only with single one. Whenever message is either received or sent, AfterReceive or BeforeSent method is invoked respectively. There you retrieve headers and if token does not match any expected you can throw an exception. Such a way out provides separation between exposed contract and background checks such as token validation.
Custom class deriving IOperationInvoker. Within custom operation invoker you explicitly call method and thanks to it you can examine headers (OperationContext.Current.IncomingMessage) before any method gets invoced.
I brought up only concepts, extensive information and examples can be looked up on Internet.
I'm new to Web Services from C#, but have worked C# for years, just never needed to use Web Services. Due to privacy issues, I can't disclose actual URL, but there is a test server and a production server where the web services are identical in all other respects, and the services were written / managed by another entity.
https://LiveSite.SomeDomain.com/FolderInWebSite/TestWebServiceSoapHTTP
and
https://TestSite.SomeDomain.com/FolderInWebSite/TestWebServiceSoapHTTP
Do I need to create two separate web references to the project and create different instances of them to go, or can I via some property just change which URL version it is sending data to.
Additionally, not being familiar working web services, I see the classes as Visual Studio imported. I can create instances of the classes and set the applicable properties (int, dates, strings, string[] arrays, etc). But not seeing how to actually say ... Go send it now. and then getting the response back.
I've done this from an older application with another language and was doing direct with HTTP and SOAP where I was able to make my own connection to the URL, build the body of the SOAP message, then send it.
Just use the "Url" property.
var myProxy = new MyProxy();
myProxy.Url = "http://foo.com/myservice";
Edit for second part of the question:
There should be a method for each action exposed the API that you can call. For example if the API exposes a MyAction that takes a string, the code generator should have generated a method that you can use like so:
myProxy.MyAction("hello");
I have a WSDL from which I generated the implementation of ClientBase namely MyService
function void updateData(Data data){
BasicHttpBinding binding = new BasicHttpBinding();
// see there is naked username and password.
EndpointAddress address = new EndpointAddress("http://qa.farwaha.com/eai_enu/start.swe?SWEExtSource=WebService&SWEExtCmd=Execute&UserName=john&Password=johspassword");
MyService service = new MyService(binding, address);
try{
service.update(data);
}finally{
service.close();
}
}
Unfortunately, to call this web service I have to pass User name and password as shown in the code. so, my question is around best practices.
Given that its a Winform Application.
How memory / CPU intensive is creating MyService object?
If you suggest cashing the service, it will hold on to the EndpointAddress; which intern has a string with Username and Password. Which is not a good idea .. any work arounds?
If I keep the code as such, service object will be garbage collected .. and there will be no trace of user name or password (as soon as GC runs)
This is a sample code, I have User Object which stores password in SecureString and every time I have to access the password; I get string from SecureString in an instance private method, use it quickly and let it be garbage collected. I believe if I use a method something like above, it will be safe OR safe enough rather than holding on to reference of Service, What do you suggest !!
To your specific questions:
In your client code, what you're constructing are instances of lightweight proxy classes that wrap the channel infrastructure that serialize messages to/from the service's endpoints. As such, these client proxy classes are cheap and fast to construct because they don't generally do a great deal until you actually send something to the service. One thing to watch out for is when you call services which employ a more complex security scheme - establishing connections to such services can be costly and so it's worth caching or re-using such connections if you can.
"Any workarounds"? Nope! Alas, the service you're consuming is poorly designed - not only do they require username and password to be supplied as part of the service method invocation, but they require that you pass them in the clear over HTTP. You might want to ask them to AT LEAST provide an SSL endpoint so that the username and password can be secured during transit. Better still, they could implement basic-auth to allow you to acquire an HTTP auth cookie that you can attach to subsequent calls against their services.
Yes, the GC will eventually clean-up your proxy instances. Better still, you could wrap your instances in using statements to invoke the Dispose pattern and clean-up deterministically. See my Magic8Ball WCF Service on Codeplex for examples.
Other observations:
Because your service requires your username and passoword, each time you call it, you need to pay some very careful thought to how you're going to obtain and store the username and password.
I would urge you to specify your binding information in the app.config rather than inline in your code. Again, see the Magic8Ball WCF Service: If you create bindings in code and the endpoint changes or if they open up a new endpoint, protocol, encoding and/or binding, you'll have to recompile and redist your entire app. If you specify your bindings in config, you might just be able to get away with shipping an updated app.config.
Hope this helps.