I am trying to call the following POST method [http://localhost:45361/api/test], in Fiddler, with [Request Header] tab, having [User-Agent: Fiddler, Content-Type: application/json; charset=utf-8] and in the [Request Body],I am passing the following request {"tag":"5667"} . However, its outputting an error -- > Object reference not set to an instance of an object.
[HttpPost]
public HttpResponseMessage post([FromBody] Query query)
{
IQueryable<data_qy> Data = null;
if (!string.IsNullOrEmpty(query.tag)) //--> line causing the ERROR
{
var ids = query.tag.Split(',');
var dataMatchingTags = db.data_qy.Where(c => ids.Contains(c.TAG));
if (Data == null)
Data = dataMatchingTags;
else
Data = Data.Union(dataMatchingTags);
}
if (!string.IsNullOrEmpty(query.name))
{
var ids = query.name.Split(',');
var dataMatchingTags = db.data_qy.Where(c => ids.Any(id => c.Name.Contains(id)));
if (Data == null)
Data = dataMatchingTags;
else
Data = Data.Union(dataMatchingTags);
}
if (Data == null)
Data = db.data_qy;
if (query.endDate != null)
{
Data = Data.Where(c => c.UploadDate <= query.endDate);
}
if (query.startDate != null)
{
Data = Data.Where(c => c.UploadDate >= query.startDate);
}
var data = Data.ToList();
if (!data.Any())
{
var message = string.Format("No data found");
return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
}
return Request.CreateResponse(HttpStatusCode.OK, data);
}
Edit:
Query Class:
public class Query
{
public string name { get; set; }
public string tag{ get; set; }
public Nullable<DateTime> startDate { get; set; }
public Nullable<DateTime> endDate{ get; set; }
}
I am little unclear, if this is the correct approach to testing post method or if I need add further code in my above controller. Please advice. Many thanks.
One of the most important things that you need in fiddler is the Content-Type header specification in the post request. Web API has this concept of content negotiation based on request headers and the registration of the content negotiators in the pipeline. Please, see here for more details.
In your case:
Content-Type: application/json; charset=utf-8
Here is the whole request from the fiddler composer:
User-Agent: Fiddler
Host: localhost:26572
Content-Length: 16
Content-Type: application/json; charset=utf-8
and here is the request body:
{"name":"hello"}
With this post request, you should be able to proceed.
Related
I am trying to add a contact email address to a existing campaign list named- "liakat". But I am getting a response from getresponse.com saying httpStatus 400, which you can check on the attached pitures. I have added a temporary api key, so you can test it yourself too. I am following this document from getresponse.com. Anyone who can fix this issue?
Controller:
string email = "test#gmail.com";
// Test Campaign name - "pikaa"
// "pikaa" named campaign ID->ee104303
// our api key-> 948dsdfsdfs1a017a07f3c6
var client = new RestClient("https://api.getresponse.com/v3/contacts");
var request = new RestRequest(Method.POST);
request.RequestFormat = DataFormat.Json;
var root = new RootObject();
root.campaign = new Campaign();
root.name = "Mr Men";
root.email = "test#gmail.com";
root.campaign.campaignId = "IDss6604303";
var jsBody = new JavaScriptSerializer().Serialize(root);
request.AddHeader("X-Auth-Token", "api-key 948sdfsdfsdfsdfsdfs6");
request.AddParameter("application/x-www-form-urlencoded", "email=" + email + "&campaign=ID85104303", ParameterType.RequestBody);
var response = client.Execute(request);
Model:
public class Campaign
{
public string campaignId { get; set; }
}
public class RootObject
{
public string name { get; set; }
public string email { get; set; }
public Campaign campaign { get; set; }
}
There is no "connection" between the Request request and the JSON Object jsBody (or root). What you're sending is a query string.
Something like
email=test#gmail.com&campaign=ID85104303
This is defined by the line:
request.AddParameter("application/x-www-form-urlencoded", "email=" + email + "&campaign=ID85104303", ParameterType.RequestBody);
If you want to send your JSON, you need to change the line to:
request.AddParameter("application/json; charset=utf-8", jsBody, ParameterType.RequestBody);
I can't tell if this will already work, but so you're at least sending the right body and you should get a successful response or at least a better error message.
[HttpDelete]
public HttpResponseMessage Delete(string id)
{
string status = "";
int _id = Convert.ToInt16(id);
tbl_machinedieselInfo data= db.tbl_machinedieselInfo.Where(x=>x.Id==_id).FirstOrDefault();
if (data.Id > 0)
{
db.tbl_machinedieselInfo.Remove(data);
db.SaveChanges();
status = "Deleted";
}
else {
status = "Bad Request";
}
return Request.CreateResponse(HttpStatusCode.OK, status);
}
I try to delete record using above api but it throws an error("HTTP Error 405"), for testing these api I am using postman and fiddler, it works properly on local host but does not work on IIS, please help.
My project is brand new Asp.net 2015 MVC6 beta 8 web application.
I get value as null when I call Web api with post type from C# code.
My server side code:
// POST api/values
[HttpPost]
public void Post([FromBody]string value)
{
if( null != value )
do something;
}
My clientside is:
StringContent cstrJson = new StringContent("{ mesage: hello}"
, System.Text.Encoding.Unicode, "application/x-www-form-urlencoded");
var result = await client1.PostAsync("http://localhost:68888/api/myApi/", cstrJson);
I tried all different combinations of encoding and media, but no improvements.
It's null because the body couldn't be parsed as a string. The content type is application/x-www-form-urlencoded instead of text/plain.
You may want to rethink using a string anyway if your client is sending json, you should accept application/json on the server and let the framework parse it for you.
[HttpPost]
public void Post(MyObject value)
{
var msg = value.Message;
}
public class MyObject
{
public string Message { get; set; }
}
Client Side:
var cstrJson = new StringContent("{'Message' : 'hello'}", System.Text.Encoding.Unicode, "application/json");
var result = await client1.PostAsync("http://localhost:68888/api/myApi/", cstrJson);
I am relatively new to Web Api and I am having trouble POSTing a Person object. If I run in debug, I see that my uriString never gets set and I don't understand why. Because of this, I get "400 Bad Request" errors in Fiddler for all attempted Posts.
I have tried replicating what others have done when it comes to the Post action. Every example I've found uses a repository to add the person to the database. I do not have repositories however, but instead am using the NHibernate Save method to carry out this functionality. Here are the domain class, mapping by code file, WebApiConfig, and the PersonController.
public class Person
{
public Person() { }
[Required]
public virtual string Initials { get; set; }
public virtual string FirstName { get; set; }
public virtual char MiddleInitial { get; set; }
public virtual string LastName { get; set; }
}
public class PersonMap : ClassMapping<Person>
{
public PersonMap()
{
Table("PERSON");
Lazy(false);
Id(x => x.Initials, map => map.Column("INITIALS"));
Property(x => x.FirstName, map => map.Column("FIRST_NAME"));
Property(x => x.MiddleInitial, map => map.Column("MID_INITIAL"));
Property(x => x.LastName, map => map.Column("LAST_NAME"));
}
}
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
config.Services.Replace(typeof(IHttpActionSelector), new HybridActionSelector());
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}/{action}/{actionid}/{subaction}/{subactionid}",
defaults: new { id = RouteParameter.Optional, action = RouteParameter.Optional,
actionid = RouteParameter.Optional, subaction = RouteParameter.Optional, subactionid = RouteParameter.Optional }
);
config.BindParameter( typeof( IPrincipal ), new ApiPrincipalModelBinder() );
// Uncomment the following line of code to enable query support for actions with an IQueryable or IQueryable<T> return type.
// To avoid processing unexpected or malicious queries, use the validation settings on QueryableAttribute to validate incoming queries.
// For more information, visit http://go.microsoft.com/fwlink/?LinkId=279712.
//config.EnableQuerySupport();
// To disable tracing in your application, please comment out or remove the following line of code
// For more information, refer to: http://www.asp.net/web-api
config.EnableSystemDiagnosticsTracing();
}
}
public class PersonsController : ApiController
{
private readonly ISessionFactory _sessionFactory;
public PersonsController (ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
}
// POST api/persons
[HttpPost]
public HttpResponseMessage Post(Person person)
{
var session = _sessionFactory.GetCurrentSession();
using (var tx = session.BeginTransaction())
{
try
{
if (!ModelState.IsValid)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
var result = session.Save(person);
var response = Request.CreateResponse<Person>(HttpStatusCode.Created, person);
string uriString = Url.Route("DefaultApi", new { id = person.Initials });
response.Headers.Location = new Uri(uriString);
tx.Commit();
return response;
}
catch (Exception)
{
tx.Rollback();
}
throw new HttpResponseException(HttpStatusCode.BadRequest);
}
}
}
Fiddler information:
POST //localhost:60826/api/employees HTTP/1.1
Request Headers:
User-Agent: Fiddler
Content-Type: application/json
Host: localhost:xxxxx
Content-Length: 71
Request Body:
{
"Initials":"MMJ",
"LastName":"Jordan",
"FirstName":"Michael"
}
This line never sets the uriString to the correct value. string uriString = Url.Route("DefaultApi", new { id = person.Initials });
I've also tried using Url.Link instead of Url.Route. I've tried adding the controller = "Persons" inside the 'new' block, but that had no effect. Why isn't uriString being set? I'll listen to any thoughts at this point.
EDIT
I have tried
string uriString = Url.Link("DefaultApi", new { controller = "Persons", id = person.Initials, action="", actionid="", subaction="", subactionid="" });
as well as using a separate routeconfig
config.Routes.MapHttpRoute(
name: "PostApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional
} );
with
string uriString = Url.Link("PostApi", new { controller = "Persons", id = person.Initials});
and have had no luck.
SOLUTION
I was able to get this Post to work by using the line of code below. I'm not entirely sure if this is the correct way to do it, so if anybody knows differently, please share. Otherwise, I will happily use this approach.
response.Headers.Location = new Uri(this.Request.RequestUri.AbsoluteUri + "/" + person.Initials);
Problem seems to be here:
string uriString = Url.Route("DefaultApi", new { id = person.Initials });
You are only passing id while you need to be passing other parameters such as controller, etc.
You may construct URL this way:
string uriString = Url.Action("ActionName", "ControllerName", new { Id = person.Initials });
In an effort to make a progress reporting process a little more reliable and decouple it from the request/response, I am performing the processing in a Windows Service and persisting the intended response to a file. When the client starts polling for updates, the intention is that the controller returns the contents of the file, whatever they are, as a JSON string.
The contents of the file are pre-serialized to JSON. This is to ensure that there is nothing standing in the way of the response. No processing needs to happen (short of reading the file contents into a string and returning it) to get the response.
I initially though this would be fairly simple, but it is not turning out to be the case.
Currently my controller method looks thusly:
Controller
Updated
[HttpPost]
public JsonResult UpdateBatchSearchMembers()
{
string path = Properties.Settings.Default.ResponsePath;
string returntext;
if (!System.IO.File.Exists(path))
returntext = Properties.Settings.Default.EmptyBatchSearchUpdate;
else
returntext = System.IO.File.ReadAllText(path);
return this.Json(returntext);
}
And Fiddler is returning this as the raw response
HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Mon, 19 Mar 2012 20:30:05 GMT
X-AspNet-Version: 4.0.30319
X-AspNetMvc-Version: 3.0
Cache-Control: private
Content-Type: application/json; charset=utf-8
Content-Length: 81
Connection: Close
"{\"StopPolling\":false,\"BatchSearchProgressReports\":[],\"MemberStatuses\":[]}"
AJAX
Updated
The following will likely be changed later, but for now this was working when I was generating the response class and returning it as JSON like a normal person.
this.CheckForUpdate = function () {
var parent = this;
if (this.BatchSearchId != null && WorkflowState.SelectedSearchList != "") {
showAjaxLoader = false;
if (progressPending != true) {
progressPending = true;
$.ajax({
url: WorkflowState.UpdateBatchLink + "?SearchListID=" + WorkflowState.SelectedSearchList,
type: 'POST',
contentType: 'application/json; charset=utf-8',
cache: false,
success: function (data) {
for (var i = 0; i < data.MemberStatuses.length; i++) {
var response = data.MemberStatuses[i];
parent.UpdateCellStatus(response);
}
if (data.StopPolling = true) {
parent.StopPullingForUpdates();
}
showAjaxLoader = true;
}
});
progressPending = false;
}
}
The issue, I believe, is that the Json action result is intended to take an object (your model) and create an HTTP response with content as the JSON-formatted data from your model object.
What you are passing to the controller's Json method, though, is a JSON-formatted string object, so it is "serializing" the string object to JSON, which is why the content of the HTTP response is surrounded by double-quotes (I'm assuming that is the problem).
I think you can look into using the Content action result as an alternative to the Json action result, since you essentially already have the raw content for the HTTP response available.
return this.Content(returntext, "application/json");
// not sure off-hand if you should also specify "charset=utf-8" here,
// or if that is done automatically
Another alternative would be to deserialize the JSON result from the service into an object and then pass that object to the controller's Json method, but the disadvantage there is that you would be de-serializing and then re-serializing the data, which may be unnecessary for your purposes.
You just need to return standard ContentResult and set ContentType to "application/json".
You can create custom ActionResult for it:
public class JsonStringResult : ContentResult
{
public JsonStringResult(string json)
{
Content = json;
ContentType = "application/json";
}
}
And then return it's instance:
[HttpPost]
public ActionResult UpdateBatchSearchMembers()
{
string returntext;
if (!System.IO.File.Exists(path))
returntext = Properties.Settings.Default.EmptyBatchSearchUpdate;
else
returntext = Properties.Settings.Default.ResponsePath;
return new JsonStringResult(returntext);
}
Yeah that's it without no further issues, to avoid raw string json this is it.
public ActionResult GetJson()
{
var json = System.IO.File.ReadAllText(
Server.MapPath(#"~/App_Data/content.json"));
return new ContentResult
{
Content = json,
ContentType = "application/json",
ContentEncoding = Encoding.UTF8
};
}
NOTE: please note that method return type of JsonResult is not working for me, since JsonResult and ContentResult both inherit ActionResult but there is no relationship between them.
Use the following code in your controller:
return Json(new { success = string }, JsonRequestBehavior.AllowGet);
and in JavaScript:
success: function (data) {
var response = data.success;
....
}
All answers here provide good and working code. But someone would be dissatisfied that they all use ContentType as return type and not JsonResult.
Unfortunately JsonResult is using JavaScriptSerializer without option to disable it. The best way to get around this is to inherit JsonResult.
I copied most of the code from original JsonResult and created JsonStringResult class that returns passed string as application/json. Code for this class is below
public class JsonStringResult : JsonResult
{
public JsonStringResult(string data)
{
JsonRequestBehavior = JsonRequestBehavior.DenyGet;
Data = data;
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
if (JsonRequestBehavior == JsonRequestBehavior.DenyGet &&
String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException("Get request is not allowed!");
}
HttpResponseBase response = context.HttpContext.Response;
if (!String.IsNullOrEmpty(ContentType))
{
response.ContentType = ContentType;
}
else
{
response.ContentType = "application/json";
}
if (ContentEncoding != null)
{
response.ContentEncoding = ContentEncoding;
}
if (Data != null)
{
response.Write(Data);
}
}
}
Example usage:
var json = JsonConvert.SerializeObject(data);
return new JsonStringResult(json);