How tu update database using ajax and the PUT verb? - javascript

I'm trying to update a property in my database called "Estado". I'm using ajax to do it, like so:
function atualizaBD(idmarcador, novoEstado) {
$.ajax
({
url: `/api/IgnicoesAPI/${idmarcador}`,
type: 'PUT',
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: JSON.stringify({ Id: idmarcador, Estado: novoEstado }),
async: true,
processData: false,
cache: false,
success: function (result) {
connection.invoke("PostMarker").catch(function (err) {
return console.error(err.toString());
});
},
error: function () {
alert("ocorreu um erro!")
}
});
}
Here is my model:
public class Ignicoes
{
public Ignicoes()
{
ListaOcorrencias = new HashSet<Ocorrencias>();
}
[Key]
public int Id { get; set; }
[Required]
public string Latitude { get; set; }
[Required]
public string Longitude { get; set; }
//estado(recusada, aceite, em avaliacao, concluido)
//public string Estado { get; set; }
[Required]
public string Estado { get; set; }
public DateTime DataInicioPropostaIgnicao { get; set; }
public DateTime DataDecisaoIgnicao { get; set; }
//lista de ocorrencias
public virtual ICollection<Ocorrencias> ListaOcorrencias { get; set; }
}
Here is my PUT method:
public async Task<IActionResult> PutIgnicoes([FromRoute] int id, [FromBody] Ignicoes ignicao)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != ignicao.Id)
{
return BadRequest();
}
else
{
var dataDecisao = DateTime.Now;
var ig = _context.Ignicoes.FirstOrDefault(ignicaoId => ignicaoId.Id.Equals(id));
if (ig != null)
{
ig.Estado = ignicao.Estado;
//ig.Estado = 0;
//ig.Latitude = ignicao.Latitude;
//ig.Longitude = ignicao.Longitude;
ig.DataDecisaoIgnicao = dataDecisao;
}
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!IgnicoesExists(id))
{
return NotFound();
}
else
{
throw;
}
}
}
return NoContent();
}
I already tried to use this code, but instead of changing the property "Estado" I changed the property "Latitude" and it worked perfectly. I don't know why this is happening. Both "Latitude" and "Estado" are the same type - String. Can somebody see the error?
Here is what appears in my output tab:
Here is the Network Analysis:
{"errors":{"Latitude":["The Latitude field is required."],"Longitude":["The Longitude field is required."]},"type":"https://tools.ietf.org/html/rfc7231#section-6.5.1","title":"One or more validation errors occurred.","status":400,"traceId":"|43114da6-4594b09a6260f1a2."}

It would be easier to undestand the problem if you had added ajax http request + response logs as well (status and payloads). However, application output says 400 bad request for your API method ivocation.
Based on your resource class you have three properties declared as [Required] (except Id) : Longitude, Latitude, Estado, but in your ajax call you are passing only ID and Estado. More likely (if you are using asp.net validation) you have 400 response because of missing required properties in your ajax request body. Try to add missing properties data: JSON.stringify({ Id: idmarcador, Estado: novoEstado, string: latitude, string: longitude })

Related

How to change variable value using PUT method?

I need to change the value of a variable when a button is clicked. For that I made a function that updates the database using ajax. Here is what I have so far:
function atualizaBD(novoEstado) {
$.ajax
({
url:`/api/IgnicoesAPI/${id}`,
type: 'PUT',
contentType: "application/json; charset=utf-8",
data: JSON.stringify({
Id : id,
Estado: novoEstado
}),
success: function (result) {
alert(result);
},
error: function () {
alert("ocorreu um erro!")
}
});
}
I have a variable called Estado and I want to change the value of that variable to a new one, novoEstado.
Here is my controller:
[HttpPut("{id}")]
public async Task<IActionResult> PutIgnicoes([FromRoute] int id, [FromBody] Ignicoes ignicao, string novoEstado)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != ignicao.Id)
{
return BadRequest();
}
var ig = _context.Ignicoes.FirstOrDefault (ignicaoId => ignicaoId.Id.Equals(id));
ig.Estado = novoEstado;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!IgnicoesExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
Right now, everytime the function an error occurs alerting "ocorreu um erro"
Here is my Model:
public class Ignicoes
{
public Ignicoes()
{
ListaOcorrencias = new HashSet<Ocorrencias>();
}
[Key]
public int Id { get; set; }
public string Latitude { get; set; }
public string Longitude { get; set; }
//estado(recusada, aceite, em avaliacao, concluido)
public string Estado { get; set; }
public DateTime DataInicioPropostaIgnicao { get; set; }
public DateTime DataDecisaoIgnicao { get; set; }
//lista de ocorrencias
public virtual ICollection<Ocorrencias> ListaOcorrencias { get; set; }
}
}

ASP.Net Core 3 Posting JSON array to controller

I´m having issues passing an array of JSON objects to an MVC controller in ASP.Net core 3. The JSON object is built from a CSV file and passed through an AJAX call. The correct action is called but the object received is always null.
JS:
async function updateData(){
var obj = await getData();
$.ajax({
type: "POST",
contentType: "application/json",
url: "/admin/metric/Update",
data: obj,
dataType: 'json',
success: function (data) {
console.log("SUCCESS : ", data);
},
error: function (e) {
console.log("ERROR : ", e);
}
});
}
async function getData(){
var metric = {};
var metrics = [];
var response = await fetch('https://bloburi.net/source/file.csv');
var data = await response.text();
var table = data.split('\n').slice(1);
table.forEach(row => {
var columns = row.split(',');
metric["FirstName"] = columns[0];
metric["LastName"] = columns[1];
metric["Email"] = columns[2];
metric["AverageHandleTime"] = columns[3];
metric["AverageFollowUp"] = columns[4];
metric["AverageHold"] = columns[5];
metric["Date"] = columns[6];
metrics.push(JSON.stringify(metric));
});
console.log(metrics);
return metrics;
}
Models:
public class MetricBase
{
[Required]
public string Date { get; set; }
public double AverageHandleTime { get; set; }
public double AverageHold { get; set; }
public double AverageFollowUp { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class MetricModel
{
public IEnumerable<MetricBase> MetricBase { get; set; }
}
Controller:
[HttpPost]
public IActionResult Update([FromBody]MetricModel obj)
{
return Json(new { obj });
}
I think the issue may be on how I'm deffining the class that is receiving the JSON, but I've tried multiple things like deffining MetricBase as a List<> or straight up as an array in MetricModel, but it doesn't seem to work.
Any help is appreciated!
You adding the stringify item inside array via code
metrics.push(JSON.stringify(metric));
instead of stringify the whole array. Change the line to
metrics.push(metric);
and data: obj, to
data: JSON.stringify(obj),.
With the mentioned change, the $.ajax sends the whole array. Also change the action to
public IActionResult Update([FromBody]IEnumerable<MetricBase> obj)

Can not get value by ajax query

I using .net core. Have this class:
public class SentEmailItem
{
public SentEmailItem()
{
Attachments = new List<AttachmentItem>();
}
public long PKID { get; set; }
public string EmailTo { get; set; }
public string EmailFrom { get; set; }
public string Cc { get; set; }
public string Bcc { get; set; }
public string Body { get; set; }
public string Subject { get; set; }
public List<string> EmailToList => EmailTo.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList();
public List<string> CcList => (Cc ?? string.Empty).Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList();
public List<string> BccList => (Bcc ?? string.Empty).Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList();
public List<AttachmentItem> Attachments { get; set; }
}
And this method in controller:
[HttpPost]
public JsonResult SendEmail(SentEmailItem item)
{
EmailHelper.SendEmailAsync(item);
return SuccessJsonResult();
}
But when called this method from ajax by this code:
$.ajax({
type: "POST",
url: self.sendEmailUrl,
contentType: "application/json",
dataType: "json",
data: JSON.stringify({ item: emaiItem })
}).done(function (json) {
App.unblockUI();
if (json.HasErrors) {
var errorsHtml = $.map(json.Errors, function (x) { return "" + x.ErrorMessage + "<br/>"; }).join("");
UIToastr.ShowMessage('error', 'Error', errorsHtml);
return;
}
self.sendEmailCompleted(json);
});
I can't get data in my controller method. All data have null value. But in emaiItem placed in js value looks like:
Bcc : "Testmail#mail.com"
Body : "test body"
Cc : "Testmail#mail.com"
EmailFrom : "just3f#mail.com"
EmailTo : "Testmail#mail.com"
Subject : "Test subject"
It seems like emaiItem is already an object like this -
var emaiItem = {Bcc : "Testmail#mail.com",
Body : "test body",
Cc : "Testmail#mail.com",
EmailFrom : "just3f#mail.com",
EmailTo : "Testmail#mail.com",
Subject : "Test subject"};
If so, it could just use JSON.stringify(emaiItem). Otherwise, you can hard-code the above emaiItem, and see those values populated at server-side.
$.ajax({
...
data: JSON.stringify(emaiItem)
}).done(function (json) {
...
});
Solution
Replace with JSON.stringify(emaiItem), and use [FromBody] attribute to force model binder to bind data from the request body.
[HttpPost]
public JsonResult SendEmail([FromBody]SentEmailItem item)
{
}
Have you tried debugging your c# code to see if the back-end api is being hit? That would be a good place to start if not.

AngularJS ngResource POST object is Null in C# Web API

My problem is that when I send a complete Javascript object to my Web API Controller I always get null values. Even though I have a complete object I need to specify each attribute and value as you can see below. How can I make Web API accept a ready made Javascript object and bind it correctly?
C# Web Api Controller:
[Route("addcredentials/{salesId}")]
[HttpPost]
public IHttpActionResult AddCredentials([FromUri] int salesId, [FromBody] ScriveCredentials credentials)
{
return Ok(credentials);
}
C# Credentials object:
public class Credentials
{
public string ClientIdentifier { get; set; }
public string ClientSecret { get; set; }
public string TokenIdentifier { get; set; }
public string TokenSecret { get; set; }
}
Javascript object passed to resource, saved as "result" further down:
{ClientIdentifier: "a", ClientSecret: "b", TokenIdentifier: "c", TokenSecret: "d"}
Resource method:
addCredentials: {
method: 'POST',
url: 'api/addcredentials/:userSalesId'
}
Usage that results in null values:
userResource.addCredentials({ userSalesId: user.SalesId }, { credentials: result}).$promise.then(function (data) {
console.log(data);
});
Payload for this request:
{"credentials":{"ClientIdentifier":"a","ClientSecret":"b","TokenIdentifier":"c","TokenSecret":"d"}}
Usage that works but seems overly complicated:
userResource.addCredentials({ userSalesId: user.SalesId }, { ClientIdentifier: result.ClientIdentifier, ClientSecret: result.ClientSecret, TokenIdentifier: result.TokenIdentifier, TokenSecret: result.TokenSecret }).$promise.then(function (data) {
console.log(data);
});
Request payload:
{"ClientIdentifier":"a","ClientSecret":"b","TokenIdentifier":"c","TokenSecret":"d"}
Update
Tried the following and it did not work either, null on all values:
addScriveCredentials: {
method: 'POST',
url: 'api/addcredentials/'
result.SalesId = user.SalesId;
userResource.addCredentials({}, { credentials: result }).$promise.then(function (data) {
console.log(data);
});
C#:
[Route("addcredentials")]
[HttpPost]
public IHttpActionResult Addcredentials(Credentials credentials)
{
return Ok(credentials);
}
I had done a sample earlier, hope the follwing code will help you to understand.
The Model.
using System.ComponentModel.DataAnnotations;
public class ProductModel
{
public ProductModel(int id, string name, string category, decimal price)
{
Id = id;
Name = name;
Category = category;
Price = price;
}
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Category { get; set; }
[Required]
public decimal Price { get; set; }
}
The ApiController.
using Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Hosting;
using System.Web.Http;
public class ProductsController : ApiController
{
// other code omitted for brevity.
[HttpPost]
public IHttpActionResult PostProduct(ProductModel product)
{
try
{
if (product == null)
{
throw new ArgumentNullException("Product parameter cannot be null");
}
if (ModelState.IsValid)
{
// code omitted for brevity.
return this.Ok();
}
else
{
throw new Exception("Product is invalid");
}
}
catch (Exception ex)
{
return InternalServerError(ex);
}
}
[HttpPut]
public IHttpActionResult PutProduct(ProductModel product)
{
try
{
if (product == null)
{
throw new ArgumentNullException("Product parameter cannot be null");
}
if (ModelState.IsValid && product.Id > 0)
{
// code omitted for brevity.
return this.Ok();
}
else
{
throw new Exception("Product is invalid");
}
}
catch (Exception ex)
{
return InternalServerError(ex);
}
}
// other code omitted for brevity.
}
The Angular service.
// products.js
(function () {
"use strict";
angular
.module("exampleApp")
.constant("baseUrl", "http://localhost:53631/api/products/")
.factory("productsResource", productsResource);
productsResource.$inject = ["$resource", "baseUrl"];
function productsResource($resource, baseUrl) {
return $resource(baseUrl + ":id",
{
id: "#id"
},
{
create: {
method: "POST"
},
save: {
method: "PUT"
}
});
}
})();
The Angular controller. Focus on createProduct and updateProduct functions below
// edit.controller.js
(function () {
"use strict";
angular
.module("exampleApp")
.controller("EditController", EditController);
EditController.$inject = ["$routeParams", "$location", "productsResource"];
function EditController($routeParams, $location, productsResource) {
var vm = this;
vm.currentProduct = null;
vm.createProduct = createProduct;
vm.updateProduct = updateProduct;
vm.saveEdit = saveEdit;
vm.cancelEdit = cancelEdit;
if ($location.path().indexOf("/edit/") === 0) {
var id = $routeParams.id;
productsResource.get({ id: id }, function (data) {
vm.currentProduct = data;
});
}
function cancelEdit() {
$location.path("/list");
}
function updateProduct(product) {
product.$save().then(function () {
$location.path("/list");
});
}
function saveEdit(product) {
if (angular.isDefined(product.id)) {
vm.updateProduct(product);
} else {
vm.createProduct(product);
}
vm.currentProduct = {};
}
function createProduct(product) {
new productsResource(product).$create().then(function (newProduct) {
$location.path("/list");
});
}
}
})();
You could pass one object as the body of the post message instead.
Add a class like this
public class addCredentialObj
{
public int salesId { get; set; }
public Credentials credentials { get; set; }
}
Modify your controller like this (The use of FromBody can be read here)
[Route("addcredentials")]
[HttpPost]
public IHttpActionResult AddCredentials([FromBody]addCredentialObj obj)
{
return Ok(credentials);
}
In the client you need to create a matching json object to the addCredentialObj class
var yourCredentials = {"ClientIdentifier":"a","ClientSecret":"b","TokenIdentifier":"c","TokenSecret":"d"};
var jsonData = {
salesId: yourId,
credentials: yourCredentials
};
And then in the $http request to the controller, stringify the json object
$http({
method: 'POST',
url: 'api/addcredentials',
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json'
},
data: JSON.stringify(jsonData),
});

Receiving object properties are null on server after an ajax put request

I've a problem with sending data form the browser to an API on my server by an ajax request to the server (method is PUT). Here is my JavaScript code:
var json = JSON.stringify({
StemType: {
ID: parseInt(this.dataset.id),
Type: this.dataset.type,
GebruikerID: "#(Model.DeTopic.Gebruiker.Id)"
},
Punten: parseInt(this.dataset.punten),
GestemdeGebruikerID: "#(Model.AangemeldeGebruiker)"
});
$.ajax({
url: "../Stem/Toevoegen",
type: "PUT",
data: json,
success: function (returnData) {
// my code
}
});
This is the json code in the variable json:
{
"StemType": {
"ID": 24731,
"Type": "Topic",
"GebruikerID": "539e6078"
},
"Punten": 1,
"GestemdeGebruikerID": "3aedefab"
}
And here is the C# code on the server.
public class StemController : ApiController
{
[HttpPost]
[Authorize]
[Route("Stem/Toevoegen")]
public void Toevoegen([FromBody]Stem stem)
{
Console.WriteLine(stem.ToString());
}
}
Here is the class Stem:
public class Stem
{
public StemType StemType { get; set; }
public int Punten { get; set; }
public string GestemdeGebruikerID { get; set; }
}
public class StemType
{
public int ID { get; set; }
public Type Type { get; set; }
public string GebruikerID { get; set; }
}
But if I debug my code on the server, I've got this:
Can anyone help me?
I've found two possible ways:
Don't stringify it for send as an object.
Add contentType: "application/json" for Json code.

Categories