I have the following method in a controller in an MVC website:
[WebGet]
public void SaveInfo()
{
string make = Request.QueryString["Make"];
string model = Request.QueryString["Model"];
// Do stuff....
}
It works fine when I type the URL in the address bar, but what I need to do is call this from a Windows client. How do I do this in C#?
Thanks!
Use the WebClient class to make an HTTP request from the client. You'll need to add a reference to System.Web if your client project doesn't already have one.
using System.Net;
using System.Web;
static void SaveInfo(string make, string model)
{
using (WebClient webClient = new WebClient())
{
string response = webClient.DownloadString(
String.Format(
"http://yoursite/ControllerName/SaveInfo?make={0}&model={1}",
HttpUtility.UrlEncode(make),
HttpUtility.UrlEncode(model)
)
);
}
}
Related
Im running a exchange synchronisation application with an autogenerated Proxy Class in .NET built with Exchange2010.
Now, i need to set the HttpHeaders:
service.HttpHeaders.Add("X-AnchorMailbox", Mailbox.SMTPAddress);
service.HttpHeaders.Add("X-PreferServerAffinity", "true");
like described here:
Maintain affinity in exchange
But it refers to the EWS Managed API and i cannot find this Property in my ExchangeServiceBindingObject. So how can I set this header in my autogenerated proxy?
I would try to use the EWS Managed Api rather than trying to roll your own. If that if that is not an option, you can add httpheaders by overriding the generated GetWebRequest method on ExchangeServiceBinding to get to the headers like so:
public class ExchangeServiceBindingWithHeaders : EwsProxy.ExchangeServiceBinding
{
private NameValueCollection _customHeaders = new NameValueCollection();
public void AddHeaders(string key, string value)
{
_customHeaders.Add(key, value);
}
protected override WebRequest GetWebRequest(Uri uri)
{
HttpWebRequest req = (HttpWebRequest)base.GetWebRequest(uri);
req.Headers.Add(_customHeaders);
return req;
}
}
Then you can call the new derived class to add the custom headers:
ExchangeServiceBindingWithHeaders service = new ExchangeServiceBindingWithHeaders();
service.RequestServerVersionValue = new RequestServerVersion();
service.RequestServerVersionValue.Version = ExchangeVersionType.Exchange2010;
service.Credentials = new NetworkCredential("<username>", "<password>", "<domain>");
service.Url = #"https://<FQDN>/EWS/Exchange.asmx";
service.AddHeaders("X-AnchorMailbox", "some#emailaddress.com");
service.AddHeaders("X-PreferServerAffinity", "true");
I'm working with OAuth 2.0 for MVC, a .NET library for Oauth2. I'm building a Web Api project, however, and am hoping to get this library to work with Web Api.
The problem I'm running into is that the library uses two extension methods on the HttpRequestBase that it calls from the controller.
Here are the extension methods:
public static string GetToken(this HttpRequest request)
{
var wrapper = new HttpRequestWrapper(request);
return GetToken(wrapper);
}
public static string GetToken(this HttpRequestBase request)
{
if (request == null)
return String.Empty;
// Find Header
var headerText = request.Headers[OAuthConstants.AuthorzationHeader];
if (!String.IsNullOrEmpty(headerText))
{
var header = new AuthorizationHeader(headerText);
if (string.Equals(header.Scheme, "OAuth", StringComparison.OrdinalIgnoreCase))
return header.ParameterText.Trim();
}
// Find Clean Param
var token = request.Params[OAuthConstants.AuthorzationParam];
return !String.IsNullOrEmpty(token)
? token.Trim()
: String.Empty;
}
In the MVC project, they simply call Request.GetToken() from the controller. Of course, Web Api's request is an HttpRequestMessage. I'm afraid addressing the difference between HttpRequest and HttpRequest message is beyond my capabilities right now.
Can I convert this extension method to work with HttpRequestMessage or somehow make it work in Web Api??
Thanks!
All the properties you used to have are still available (assuming the OAuthConstants.AuthorzationParam is set on the query string?)
using System;
using System.Linq;
using System.Net.Http;
namespace YourApp
{
public static class Extensions
{
public static string GetToken(this HttpRequestMessage request)
{
if (request == null)
return String.Empty;
// Find Header
var headerText = request.Headers.GetValues(OAuthConstants.AuthorzationHeader).SingleOrDefault();
if (!String.IsNullOrEmpty(headerText))
{
//Brevity...
}
// Find Clean Param
var token = request.GetQueryNameValuePairs().SingleOrDefault(x => x.Key == OAuthConstants.AuthorzationParam).Value;
return !String.IsNullOrEmpty(token)
? token.Trim()
: String.Empty;
}
}
}
Controller
using System.Collections.Generic;
using System.Web.Http;
using YourApp;
namespace YourApp.Controllers
{
public class FoosController : ApiController
{
public IEnumerable<string> Get()
{
var token = Request.GetToken();
return null;
}
}
}
I have found several sources that say that you should not use HttpContext.Current in WebApi but none that say how you should handle those cases where we used to use HttpContext.Current.
For example, I have a LinkProvider class that creates links for an object. (simplified to stay on topic).
public abstract class LinkProvider<T> : ILinkProvider<T>
{
protected ILink CreateLink(string linkRelation, string routeName, RouteValueDictionary routeValues)
{
var context = System.Web.HttpContext.Current.Request.RequestContext;
var urlHelper = new System.Web.Mvc.UrlHelper(context);
var url = string.Format("{0}{1}", context.HttpContext.Request.Url.GetLeftPart(UriPartial.Authority), urlHelper.RouteUrl(routeName, routeValues));
///...
return new Link(linkRelation, url);
}
}
and this class is used by a MediaTypeFormatter.
This class is expected to build a link using the same host that came from the original request and leveraging any route values that were on the original request.
But... how do I get a hold of the HttpRequestMessage? This will be encapsulated by a MediaTypeFormatter - but it doesn't have one either.
There must be an easy way to get hold of the HttpRequestMessage - what am I overlooking?
thanks
Jon
I ended up creating the following base Formatter which exposes the request, now I will be able to pass it along to the LinkProvider.
public class JsonMediaTypeFormatterBase : JsonMediaTypeFormatter
{
public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, System.Net.Http.HttpRequestMessage request, MediaTypeHeaderValue mediaType)
{
Request = request;
return base.GetPerRequestFormatterInstance(type, request, mediaType);
}
protected HttpRequestMessage Request
{
get;
set;
}
}
I have created a filter which inherits the System.Web.Http.Filters.ActionFilterAttribute in the asp.net web api and would like to access some of the data inside the HttpActionExecutedContext result object.
At what stage/when does this object get populated? As I looked at it when overriding the OnActionExecuted method and its always null?
Any ideas?
Edit:
for example here in my custom filter:
public override OnActionExecuted(HttpActionExecutedContext context)
{
//context.Result.Content is always null
base.OnActionExecuted(context);
}
Use this function to get body of request in web api
private string GetBodyFromRequest(HttpActionExecutedContext context)
{
string data;
using (var stream = context.Request.Content.ReadAsStreamAsync().Result)
{
if (stream.CanSeek)
{
stream.Position = 0;
}
data = context.Request.Content.ReadAsStringAsync().Result;
}
return data;
}
Ended up using ReadAsStringAsync on the content result.
I was trying to access the property before the actual request had finished.
While the awarded answer referred to ReadAsStringAsync, the answer had no example. I followed the advice from gdp and derived a somewhat working example...
I created a single class called MessageInterceptor. I did nothing more than derive from ActionFilterAttribute and it immediately started to intercept webAPI method calls prior to the controller getting it, and after the controller finished. Here is my final class. This example uses the XML Serializer to get both the request and response into an XML string. This example finds the request and response as populated objects, this means deserialization has already occurred. Collecting the data from a populated model and serializing into an XML string is a representation of the request and response - not the actual post request and response sent back by IIS.
Code example - MessageInterceptor
using System.IO;
using System.Linq;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using System.Xml.Serialization;
namespace webapi_test
{
public class MessageInterceptor : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
base.OnActionExecuting(actionContext);
var headers = actionContext.Request.Content.Headers.ToString();
var request = actionContext.ActionArguments.FirstOrDefault().Value;
var xml = SerializeXMLSerializer(request, "");
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
base.OnActionExecuted(actionExecutedContext);
var headers = actionExecutedContext.Response.Content.Headers.ToString();
var response = actionExecutedContext.Response.Content.ReadAsStringAsync().Result;
var xml = SerializeXMLSerializer(response, "");
}
public static string SerializeXMLSerializer(object o, string nameSpace)
{
string serializedValue;
var writer = new StringWriter();
XmlSerializer serializer = new XmlSerializer(o.GetType(), nameSpace);
serializer.Serialize(writer, o);
serializedValue = writer.ToString();
return serializedValue;
}
}
}
Use below to read Response string:
public static string GetResponseContent(HttpResponseMessage Response)
{
string rawResponse = string.Empty;
try
{
using (var stream = new StreamReader(Response.Content.ReadAsStreamAsync().Result))
{
stream.BaseStream.Position = 0;
rawResponse = stream.ReadToEnd();
}
}
catch (Exception ex) { throw; }
return rawResponse;
}
Is it possible enable the Google Placess API WebService to allow cross-origin requests from my domain so that I can access the service directly from the browser? I'v been experimenting with the API-keys by creating a Browser API key and then adding my domain to the referers list, but to no avail. Not sure if that is what the refeferer property is for anyway.
Is this limitation by design, or am I missing something here?
Google Places API WebService is the service that I want to use. Neither the Places Autocomplete or Places Search in the Places Library are suitable for my particular requirement.
Cheers
Stian
This is a client-side based limitation, so the short answer is: no.
However there are websites and services that try to surmount this problem by using scripts (loading them on the fly).
Have a look here and here (these articles are about generic cross-domain AJAX requests)
The Places-API is also available inside the Maps-Javascript-API, you don't need to struggle with cross-origins there.
Let me say its impossible to get around .I tried using java instead the code just works for http request(i used here is for graph.facebook.com):
public class search {
private static String readAll(Reader rd) throws IOException {
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp);
}
return sb.toString();
}
public static JSONObject readJsonFromUrl(String url) throws IOException, JSONException {
InputStream is = new URL(url).openStream();
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String jsonText = readAll(rd);
JSONObject json = new JSONObject(jsonText);
return json;
} finally {
is.close();
}
}
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
System.getProperties().put("http.proxyHost", "172.16.0.2");
System.getProperties().put("http.proxyPort", "8080");
JSONObject json = readJsonFromUrl("http://maps.googleapis.com/maps/api/place/nearbysearch/json?key=AIzaSyBRlMLIdoTk-j4OZCucR47rVMLhMmvZVRw&type=hospital&location=12.8213125%2C80.0442&radius=500&_=1427359809583");
System.out.println(json.toString());
// System.out.println(json.get("about"));
// System.out.println("hello ");
}
}
If you replace the link with places api web search it will not work,the reason is that google does not give its services on HTTP domain,,, and my code only works on HTTP domain(not HTTPS)