I am facing a issue with mailChimp, I make a PUT call with HttpWebRequest for unsubscribing a user from the list, it works fine but the same thing I had done with POST call with status as unsubscribed then it also works. So which call should I make for unsubscription?
Example code with mailChimp Api key in added in HttpWebRequest headers:
string subscriberEmail = "XXXXXX";
//Create JSON Object for sending to MailChimp
var subscribeRequest = new
{
status = "unsubscribed",
email_address = subscriberEmail, //E-Mail
};
var requestJson = serializer.Serialize(subscribeRequest);
HttpWebRequest httpWebRequest =(HttpWebRequest)HttpWebRequest.Create(https://XXX.api.mailchimp.com/3.0/lists/XXXXXX/members");
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "text/json";
httpWebRequest.Accept = "text/json";
Rather than a hard-rule on what to choose, here is an explanation on why both Verbs work.
A lot of API providers support the same operations for both the PUT and POST verb.
In pure REST terms, these verbs have specific guidelines of POST for creating new resources and PUT for updating resources.
But in most real-world APIs, the lines blur between following 100% REST guidelines vs. providing action oriented APIs. e.g. (Unsubscribe, Cancel etc.)
In that, it really doesn't matter if you use POST or PUT and hence a lot of API providers provide support for both. Internally they tend to always go through the same code path, and hence you should see the same behavior in both cases.
When both PUT and POST are available for action oriented APIs (unsubscribe, cancel etc.) I have seen folks preferring the POST Verb, since it is more intuitive and natural on a non-read-only API.
But there is really no hard rule, so whatever you decide stick to it.
Related
I'm working on a C# console application which calls external REST APIs with RestSharp.
The issue now is that I have to access an API that only allows a custom request method like FOOBAR instead of the traditional GET or POST.
using RestSharp;
var request = new RestRequest();
request.Method = Method.POST;
Unfortunately, I haven't seen anything pertaining to custom request methods in RestSharp's docs or GitHub issues section.
Keep in mind that I only have a basic knowledge on this, so my trials might be considered silly.
I've tried assigning a string to it but it only accepts an enum.
request.Method = "FOOBAR"; // Does not accept strings
I've also tried converting a string to enum using code from this answer, but this defaults to a GET. It might be like that due to my converted string not being in their enum Method.
Enum.TryParse("FOOBAR", out Method customRequestMethod);
request.Method = customRequestMethod; // Defaults to GET
If this is not possible with RestSharp, is this feature doable with HttpClient or Flurl?
I'm new to web api and writing a code where by I'm sending in json data for a PUT/POST request to web api (web service).
I'm doing the following
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:9000/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var gizmo = some json data;
HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post,"url");
req.Content = new StringContent(some json data, Encoding.UTF8,"application/json"));
client.Timeout = TimeSpan.FromSeconds(500);
response = await client.PostAsJsonAsync("api/products", gizmo);
}
My question is do I essentially have to put the code for content-type for content header or not and I have observed that even if do include content-type as "applicatipn/json" exclusively for content-type in my code
and check my request in Fiddler, it still shows content-type :text/html. Why is that? .
All your replies will be highly appreciated
Yes, you do put code for content-type. The bit you don't have to include with JSON is the accepts, although I personally feel it is better to include accepts, as it explicitly states intent, but your mileage may vary.
Here is a blog post I just found that explains some of the issues around not doing this:
http://truncatedcodr.wordpress.com/2012/09/05/asp-net-web-api-always-set-content-type/
EDIT:
See comments. Apparently, you do not have to specify content type any more. Regardless, explicit coding is preferred to implicit coding, at least in most Enterprise software. The reason is simple: When you use implicit coding, the intent of the code is often lost. Note that I am not saying "don't use abstractions that are available", as there is nothing wrong with allowing Microsoft (or an open source development team) to take over the plumbing of your application and use the abstractions they provide to simplify and reduce your code. If you rely on defaults, rather than set the values, you create some future risk, and this should be considered. In some cases, it is worth the risk. The tendency, today, is to use implicit coding as much as possible, as it saves keystrokes. As a consultant, I can attest this is very often the core of future problems.
The lack of documentation on this subject coupled with the fact that I'm struggling with a learning curve on all fronts and making me really confused about where to start. I need to get this done using C# if possible. I apologize for the vagueness of this question, but I'm really lost. I would love links to comprehensive guides/references.
In my efforts to get this done, I've run into the following problems/questions:
I've created a web service using the otrs gui, with the operation CreateTicket, but requests via C# to my chosen namespace are returning 404 (not found). When I try to add a service reference or web reference with that namespace, I get the same error. However, when I plug that namespace into my browser as the url, it displays "customer.pl".
Can I send a soap request without adding the web service as a service reference in visual studio? Given the previous problem I'm having I can't do it that way. Would I just build the soap request string and write it to the web request's data stream with http://domain/rpc.pl as the uri?
If the answer to the previous question is yes... When trying the below code segment I get an internal server error (500) on the last line. However the header looks like a SOAP header which confuses me because I wouldn't have thought it got that far.
var document = new StringBuilder();
document.Append("<UserLogin>some user login</UserLogin>");
document.Append("<Password>some password</Password> ");
document.Append("<Ticket>");
document.Append("<Title>some title</Title> ");
document.Append("<CustomerUser>some customer user login</CustomerUser>");
document.Append("<Queue>some queue</Queue>");
document.Append("<State>some state</State>");
document.Append("<Priority>some priority</Priority>");
document.Append("</Ticket>");
document.Append("<Article>");
document.Append("<Subject>some subject</Subject>");
document.Append("<Body>some body</Body>");
document.Append("<ContentType>text/plain; charset=utf8</ContentType>");
document.Append("</Article>");
//var uri = new Uri("http://domain/injest");
var uri = new Uri("http://domain/rpc.pl");
var httpWebReq = (HttpWebRequest)WebRequest.Create(uri);
var bytePostData = Encoding.UTF8.GetBytes(document.ToString());
httpWebReq.Timeout = 5 * 1000;
httpWebReq.Method = "POST";
httpWebReq.ContentLength = bytePostData.Length;
httpWebReq.ContentType = "text/xml;charset=utf-8";
//httpWebReq.TransferEncoding=
//httpWebReq.ContentType = "application/xml";
//httpWebReq.Accept = "application/xml";
var dataStream = httpWebReq.GetRequestStream();
dataStream.Write(bytePostData, 0, bytePostData.Length);
dataStream.Close();
var httpWebResponse = (HttpWebResponse)httpWebReq.GetResponse();
Even if all you can offer is where to start, it would help me to know how to proceed, as I'm stumped.
You're using the rpc.pl endpoint which is part of the 'old' RPC-style interface.
You mention you added the web service via the GUI which means you're using the 'new' Generic Interface, which is indeed much easier from .Net.
The address of the endpoint is /otrs/nph-genericinterface.pl/Webservice/GenericTicketConnector or whatever you have called the web service in the admin section.
What is the equivalent to WebResponse.IsFromCache when using HttpClient and HttpResponseMessage?
Is there some HTTP header in the response that I can look at?
FYI: The Windows.Web.Http HttpClient (a similar API targetted at Windows 8.1 app development) does include an HttpResponseMessage.Source field that specifies where the result came from (common values are "cache" and "network").
The Windows.Web.Http classes are usable from C# and other .NET languages, from C++, and from JavaScript (when running as a WwaHost app like from the Windows app store).
Can I ask what you're trying to achieve? Are trying to avoid caching?
The reason for asking is I've looked at the source code for HttpClient (specifically HttpClientHandler) and the source for HttpWebResponse and I dont believe you can get this information from the headers.
HttpClient/HttpClientHandler does use HttpWebResponse internally however it does not expose all properties from HttpWebResponse :
private HttpResponseMessage CreateResponseMessage(HttpWebResponse webResponse, HttpRequestMessage request)
{
HttpResponseMessage httpResponseMessage = new HttpResponseMessage(webResponse.StatusCode);
httpResponseMessage.ReasonPhrase = webResponse.StatusDescription;
httpResponseMessage.Version = webResponse.ProtocolVersion;
httpResponseMessage.RequestMessage = request;
httpResponseMessage.Content = (HttpContent) new StreamContent((Stream) new HttpClientHandler.WebExceptionWrapperStream(webResponse.GetResponseStream()));
//this line doesnt exist, would be nice
httpResponseMessage.IsFromCache = webResponse.IsFromCache;// <-- MISSING!
...
}
So your options the way I see it are:
a) Look at the source code for HttpWebRequest to determine the logic for IsFromCache and retrofit this somehow into HttpClient (this may not even be possible, depends on what the logic actually does/needs)
b)ask the ASP.NET team for this property to be included with HttpResponseMessage. either directly as a property or perhaps they could 'keep' the HttpWebResponse
Neither of these options are that great sorry, hence my original question, what are you trying to acheive?
I've been struggling with this scenario recently as well.
What I needed was an integration test to verify that:
Responses for a newly created resource had the correct headers set by the server.
Subsequent requests for that resource were fulfilled from the client-cache.
Responses for an existing resource had the correct headers set by the server as well.
What I ended up doing was a twofold check:
A non-caching HttpClient to check the initial response:
new WebRequestHandler
{
AllowAutoRedirect = true,
UseCookies = true,
CookieContainer = new CookieContainer(),
CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Refresh)
};
var client = new HttpClient(handler)
and a second HTTP client to check the client-side cache:
new WebRequestHandler
{
AllowAutoRedirect = true,
UseCookies = true,
CookieContainer = new CookieContainer(),
CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Default)
};
var client = new HttpClient(handler)
To verify the source of response messages I compare the HttpResponseMessage.Headers.Date values from steps 1 and 2 (which will be the same if the response came from the client cache). For my third step I can just re-use the client from the first step and append an arbitrary string to the URL.
Disclaimer: this applies to .NET Framework 4.7 and ignores best practices concerning HttpClient usage but is seems to do the trick for me in my test suite. An explicit property like the one mentioned above would be preferable but does not seem to be available. Since the last reply here is already a few years old there might be better ways to handle this, but I couldn't think of one.
I have a simple Restful service being called from a console app so am using WebClient. I am wondering if this call for Delete is correct.
The url looks like localhost/RestService1/Person/1
using (var client = new WebClient())
{
client.UploadString(url, "DELETE", "");
}
I don't like that UploadString does not have an overload without a data parameter. The passing of an empty parameter is not sitting well with me. Is there a better method to use for a DELETE?
I could use WebRequest but I want to just use WebClient to keep it consistent.
Here is the WebRequest block
var request = WebRequest.Create(url);
request.Method = "DELETE";
var response = (HttpWebResponse)request.GetResponse();
Both blocks work fine but what is best? Or is there a better way?
The following works for me:
client.UploadValues(url, "DELETE", new NameValueCollection());
The WebClient class doesn't really lend well to restful api consumption, I've used 3rd party libraries like RestSharp in the past that are geared more towards this type of web request. I'm pretty sure RestSharp just uses HttpWebRequest under the covers, but it provides a lot of semantics that make consuming and reusing rest resources easier.
Go get the Microsoft.Net.Http client libraries http://nuget.org/packages/Microsoft.Net.Http
HttpClient is a much better client to use for working with an API.
Sorry this is my solution in vb.net i sure that anyone can translate to c#
It's very important to drop headers, i had to comment header about Accept and Content-Type and work fine..... of course I did send the token
Dim rest As WebClient = New WebClient()
rest.Headers.Add(HttpRequestHeader.Authorization, "Bearer " & Token)
'rest.Headers.Add(HttpRequestHeader.Accept, "application/json")
'rest.Headers.Add(HttpRequestHeader.ContentType, "application/json")
result = System.Text.Encoding.UTF8.GetString(rest.UploadValues(host_api & uri, "DELETE", New NameValueCollection()))