c# mvc reroute request to different server - c#

I have a web application which is a mesh of a few different servers and 1 server is the front-end server which handles all request external incoming requests.
So some of these request will have to be passed along to different servers and ideally the only thing I want to change is the host and Uri fields of these request. Is there a way to map an entire incoming request to a new outgoing request and just change a few fields?
I tried something like this:
// some controller
public HttpResponseMessage get()
{
return this.Request.Rewrite("192.168.10.13/api/action");
}
//extension method Rewrite
public static HttpResponseMessage Rewrite(this HttpRequestMessage requestIn, string Uri) {
HttpClient httpClient = new HttpClient(new HttpClientHandler());
HttpRequestMessage requestOut = new HttpRequestMessage(requestIn.Method, Uri);
requestOut.Content = requestIn.Content;
var headerCollection = requestIn.Headers.ToDictionary(x => x.Key, y => y.Value);
foreach (var i in headerCollection)
{
requestOut.Headers.Add(i.Key, i.Value);
}
return httpClient.SendAsync(requestOut).Result;
}
The issue I am having is that this has a whole slew of issues. If the request is a get Content shouldn't be set. THe headers are incorrect since it also copies things like host which shouldn't be touched afterwards etc.
Is there an easier way to do something like this?

I had to do this in C# code for a Silverlight solution once. It was not pretty.
What you're wanting is called reverse proxying and application request routing.
First, reverse proxy solutions... they're relatively simple.
Here's Scott Forsyth and Carlos Aguilar Mares guides for creating a reverse proxy using web.config under IIS.
Here's a module some dude named Paul Johnston wrote if you don't like the normal solution. All of these focus on IIS.
Non-IIS reverse proxies are more common for load balancing. Typically they're Apache based or proprietary hardware. They vary from free to expensive as balls. Forgive the slang.
To maintain consistency for the client's perspective you may need more than just a reverse proxy configuration. So before you go down the pure reverse proxy route... there's some considerations.
The servers likely need to share Machine Keys to synchronize view state and other stuff, and share the Session Store too.
If that's not consistent enough, you may want to implement session stickiness through Application Request Routing (look for Server Affinity), such that a given session cookie (or IP address, or maybe have it generate a token cookie) maps the user to the same server on every request.

I also wrote a simple but powerful reverse proxy for asp.net / web api. It does exactly what you need.
You can find it here:
https://github.com/SharpTools/SharpReverseProxy
Just add to your project via nuget and you're good to go. You can even modify on the fly the request, the response, or deny a forwarding due to authentication failure.
Take a look at the source code, it's really easy to implement :)

Related

Using Bing API: easiest way to connect with an API and get data from it

I've searched some time, looking for easy way to connect with some other sites WebAPI. There are some solutions, but they are made in very complicated way.
What I want to do:
Connect with server using URL adress
Provide login and password to get some data
Get data as JSON/XML
Save this data in an "easy-to-read" way. I mean: save it to C# variable which could be easy to modify.
Currently, API that I want to work with is Bing Search, but I'm looking for some universal way. I found an example, but it doesn't work for me and in my app I can't use this class: "DataServiceQuery" because it doesn't exsist.
How do you usually do it? Do you have your favourite solutions? Are there some universal ways or it depends on type of API that you work with?
I'm currently working on .NET MVC app (in case it could make any difference)
From server side
You can use that like below.
// Create an HttpClient instance
HttpClient client = new HttpClient();
// Send a request asynchronously continue when complete
client.GetAsync(_address).ContinueWith(
(requestTask) =>
{
// Get HTTP response from completed task.
HttpResponseMessage response = requestTask.Result;
// Check that response was successful or throw exception
response.EnsureSuccessStatusCode();
// Read response asynchronously as JsonValue
response.Content.ReadAsAsync<JsonArray>().ContinueWith(
(readTask) =>
{
var result = readTask.Result
//Do something with the result
});
});
You can see example on following link.
https://code.msdn.microsoft.com/Introduction-to-HttpClient-4a2d9cee
For JavaScirpt:
You could use jQuery and WebAPI both together to do your stuff.
There are few steps to it.
Call web api with Ajax jquery call.
Get reponse in JSON
Write javascript code to manipulate that response and do your stuff.
This is the easiest way.
See following link for reference:
http://www.codeproject.com/Articles/424461/Implementing-Consuming-ASP-NET-WEB-API-from-JQuery
It entirely depends on the type of API you want to use. From a .Net point of view, there could be .Net 2 Web Services, WCF Services and Web API Services.
Web APIs today are following the REST standard and RMM. Some APIs need API Keys provided as url parameters, others require you to put in request's header. Even some more robust APIs, use authentication schemes such as OAuth 2. And some companies have devised their own standards and conventions.
So, the short answer is that there is no universal way. The long answer comes from documentation of each API and differs from one to another.

What is an absolute bare bones httpclient configuration?

I'm coming to .net web api from a JavaScript background, and I'm trying to make a proxy to help with a cross domain JSON request. I'm GETing from a server I don't control the source code for, so I can't configure CORS directly. Likewise, it doesn't speak JSONP.
So two questions as I try to get my head around Web API:
1) Is Httpclient the right tool for this job? (if not, what is?)
2) If httpclient IS the right tool, what is an absolute bare bones httpclient config so I can test this out? Not worried about throwing exceptions or anything else other than just GETing API data and feeding it to a jQuery client.
I guess one other piece of information that would be nice would be building username / password authentication into the http request.
Any help is much appreciated, as are links to any good blogs / tutorials / etc that might help as an introduction to this sort of thing. I've watched several today alone, and I'm still not able to get a basic http request going on the server side without resorting to cutting / pasting other people's code.
Thanks in advance!
** EDIT - To make this question a bit more clear, what I'm trying to test is 1) Can the proxy connect to the third party server, which involves authentication via a username and password 2) Can the proxy then respond to the jQuery client request with the JSON data it received from the third party server.
Thanks to all who have taken the time to respond.
HttpClient seems to be ok in this job.
About the minimal config- it depends on what the third party expects. In most cases would work out-of-the-box, but there always may be some minor tweaks like headers and/or auth code.
I have just found some blog entry where some author shows how to test such a proxy and shows the proxy code too. Please see: http://www.davidbreyer.com/programming/2014/10/11/create-fake-responses-to-rest-service-calls-in-c/
You can find info about sending credentials here: How to use credentials in HttpClient in c#?
HTH
EDIT:
this sample code should work (copied from blog above and modified):
public class Proxy
{
public async Task<ExampleDto> GetExample(int id)
{
var client=new HttpClient();
//set some auth here
//set other headers
var response = client.GetAsync(
string.Format("/api/restserviceexample/{0}", id))
.Result.Content.ReadAsAsync<ExampleDto>();
return await response;
}
}
It's so simple that you can just run it and see if the other server responds. If not, you can play with headers - since all the session info and user auth info are sent using ookies and/or headers, all you have to do is to see how it's made with regular browser and then fake it on the server. Probably best tool for this job will be Fiddler.
However - there is one thing to consider. If the other service has special method for authorization (other than passing credentials with each request) the whole thing becomes tricky, since your proxy should perform authorization using their service, then store their auth cookie on the server or propagate them to the browser and attach them with all next requests.
First, you don't need ASP.NET with C# if you really want minimal.
.NET has great http handling without ASP. Check out classes like HttpListener, HttpListenerContext, HttpListenerRequest, etc... Yes, you'll have to write some boilerplate as your application, but these classes are pretty good.
See among others:
http://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=599978
Second, if you want user & password, I'd checkout using oauth authentication so you don't have to deal with them directly. Google Plus, Windows Live, Facebook, etc... all have similar OAuth 2.0 APIs for that. See among others:
http://msdn.microsoft.com/en-us/library/dn659750.aspx
https://developers.google.com/+/web/signin/server-side-flow
https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2

Caching GET requests with Web API on Azure

I'm developing a Web API RESTful service on the Azure platform.
I thought that the default client-side caching behavior would be to cache GET requests (since GET is idempotent and all).
To my surprise when I deployed the service to Azure all responses were sent with a Cache-Control: private header or other cache-disallowing header.
I tried the solution suggested in this question, it did work locally in IIS but did not work once we deployed to Azure. I could not find anything in the documentation about this ability which I thought was very basic in a RESTful service, I really hope that I'm missing something obvious, in MVC it was very easy.
tl;dr
We need to cache GET requests on the client side when using Azure and Web API.
I don't believe Azure is doing anything to you in this respect. It's a matter of you needing to specify exactly what caching properties you want for your resource(s).
With WebAPI you can control what caching properties your response has via the CacheControlHeaderValue which is accessible via the myHttpResponseMessage.Headers.CacheControl property.
Assuming you had a controller action like this:
public Foo Get(int id)
{
Foo myFoo = LoadSomeFooById(id);
return myFoo;
}
You'll need to do something like this to take control of the caching explicitly:
public HttpResponseMessage Get(int id)
{
Foo myFoo = LoadSomeFooById(id);
HttpResponseMessage myHttpResponseMessage = this.Request.CreateResponse(HttpStatusCode.OK, myFoo)
CacheControlHeaderValue cacheControlHeaderValue = new CacheControlHeaderValue();
cacheControlHeaderValue.Public = true;
cacheControlHeaderValue.MaxAge = TimeSpan.FromMinutes(30);
myHttpResponseMessage.Headers.CacheControl = cacheControlHeaderValue;
return myHttpResponseMessage;
}
Many of the other properties related to caching that you'd expect are also available on the CacheControlHeaderValue class, this is just the most basic example.
Also, bear in mind my example is extremely brute force/simplistic in that all the caching behavior/logic is right there in the action method. A much cleaner implementation might be to have an ActionFilterAttribute which contains all the caching logic based on attribute settings and applies it to the HttpResponseMessage. Then you could revert to the more model centric action method signature because you would, in this case, no longer need access to the HttpResponseMessage anymore at that level. As usual, many ways to skin the cat and you have to determine which works best for your specific problem domain.
Take a look at this http://forums.asp.net/post/4939481.aspx it implements caching as an attribute that modifies the HTTP response.
Disclaimer: I haven't tried it.
I would recommend this https://github.com/filipw/AspNetWebApi-OutputCache
Simple, quick and has various options to cache.
Hope that helps

Secure WCF REST Webservice and headers

I'm writing a secure WCF REST webservice using C#.
My code is something like this:
public class MyServiceAuthorizationManager : ServiceAuthorizationManager
{
protected override bool CheckAccessCore(OperationContext operationContext)
{
base.CheckAccessCore(operationContext);
var ctx = WebOperationContext.Current;
var apikey = ctx.IncomingRequest.Headers[HttpRequestHeader.Authorization];
var hash = ctx.IncomingRequest.Headers["Hash"];
var datetime = ctx.IncomingRequest.Headers["DateTime"];
...
I use headers (Authorization,Hash,DateTime) to store informations about apikey, current datetime and the hashed request URL while request body contains only URL and webservice parameters.
Example:
http://127.0.0.1:8081/helloto/daniele
Is this the right way or I've to pass and retieve those parameters from URL like this:
http://127.0.0.1:8081/helloto/daniele&apikey=123&datetime=20120101&hash=ddjhgf764653ydhgdhgfjiutu56
are there differences between those two methods?
I think both methods would work for simple cases. However, if you want to make maximum use of native HTTP behaviours, you should go with the headers approach, not the URL query parameters one.
This will allow you to (for example) use HTTP response codes to indicate to client that a resource has been permanently moved (response code 301) so the client can automatically update links. If the URL included the authentication information, it is not clear to a client that two different URLs are actually referring to the same resource. In other redirect scenarios, the headers will be automatically included so you don't have to worry about appending parameters to redirect URLs.
Also, it should allow better caching behaviour on clients (if that is relevant in your scenario).
As another example, using headers would allow you to authenticate a request based just on the headers without requiring the client to send the message body. The idea is that you authenticate with the headers, then send the client an HTTP 100 Continue response. The client should not send the message body until it gets the 100. This could be an important optimisation if you are doing POSTs or PUTs with large message bodies.
There are other examples, but whether any given one is relevant depends on your scenarios and on the clients you expect to serve.
In summary, I would say it is better to make use of elements of the protocol as they were explicitly intended - this gives you the best chance of behaving as a client expects and should make your service more accessible, efficient and usable in the longer term.
Based on your implementation, your required parameters would have to be passed in the HTTP Headers of the request, which would most certainly not be on the query string.

c# client calling java axis2 web service, object "resets"

I am very new to web service stuff so please be kind.
I have written a simple POJO class, and deployed it on an axis2 server:
public class Database {
private Project project;
public void login(){
project = new Project();
project.setDescription("Hello there");
project.setName("To me");
}
public Project getProject(){
return project;
}
}
I call the service from a c# client:
localhost.Database db = new WindowsFormsApplication1.localhost.Database();
db.login();
localhost.getProjectResponse pr = new WindowsFormsApplication1.localhost.getProjectResponse();
pr = db.getProject();
When I debug the response is null.
At the java end, when I call getProject, the project object is null.
What's happening?
How do I preserve the state of project between service calls?
For most toolkits, web services are stateless by default. I think axis is no different.
If you want to maintain state between calls then you will need to enable sessions. An example on how to maintain sessions in axis can be found at:
http://kickjava.com/src/test/session/TestSimpleSession.java.htm
On the .NET side you will need to assign a CookieContainer to your request to store the session identifier. See HOW TO: Use CookieContainer to Maintain a State in Web Services for more information.
I think your code would look something like this:
localhost.Database db = new WindowsFormsApplication1.localhost.Database();
// Assign the CookieContainer to the proxy class.
db.CookieContainer = new System.Net.CookieContainer();
db.login();
localhost.getProjectResponse pr = new WindowsFormsApplication1.localhost.getProjectResponse();
pr.CookieContainer = db.CookieContainer;
pr = db.getProject();
I think that should let you do what you want -- but I wouldn't recommend it.
Designing service interfaces is a bit different than designing object oriented interfaces. Service interfaces typically eschew the use of state and instead require the consumer to provide all of the relevant information in the request.
From Service-Oriented Architecture:
Services should be independent,
self-contained requests, which do not
require information or state from one
request to another when implemented.
I would definitely recommend reading that article and perhaps revisiting your design.
I'm not sure why #shivaspk left a comment instead of writing an answer, it is quite correct: web service calls (not just axis calls) are meant to be stateless, so although the project object gets created by
db.login();
when you call
db.getProject();
It is being called on a different instance of your Database class that was created by Axis to service the second call.
There is no really good answer to your question, except for you to rethink what you are trying to do. If you need some kind of authentication (via login), then that authentication needs to be part of every web service call.

Categories