Passing string from Angular to API - javascript

I want to fill in one string parameter in my ASP.NET Core MVC API controller via Angular.
I have this working call:
API
//A class to wrap my string
public class Foo
{
public string bar { get; set; }
}
[HttpPost]
public JsonResult GetDetails([FromBody] Foo bar) { ... }
Angular (service)
public get() {
let bar: any = new Object();
bar.foo = 'Hello World';
return this._httpClient.post('api/GetDetails', bar).toPromise();
}
But what I really want is pass a string without having to wrap it in a class like this:
API
[HttpPost]
public JsonResult GetDetails([FromBody] string bar) { ... }
Angular (service)
public get() {
let bar: string = "Hello World";
return this._httpClient.post('api/GetDetails', bar).toPromise();
}
But I get errors like it's an Unsupported Media Type or 'bar' stays null.
What is the right syntax to just pass one value?
The other thing is, I can pass an integer from Angular to the API just fine but not a string.

Try this :
let bar = JSON.stringify({'foo' : 'Hello World'});
let body = new HttpParams();
body = body.set('bar', bar);
http.post('/api/GetDetails', body).subscribe();

2 ways, depending on whether you have control over back or front end.
1. Angular-service
Use header application/json; charset=utf-8 as described here and here (note the charset)
2. API
The other one is to build a custom string-binder derived which spits out a string.
[HttpPost]
public JsonResult GetDetails([ModelBinder(typeof(StringBinder))] string bar) { ... }
where
public class StringBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
throw new ArgumentNullException(nameof(bindingContext));
using (var sr = new StreamReader(bindingContext.HttpContext.Request.Body))
Body = sr.ReadToEnd();
bindingContext.Result = ModelBindingResult.Success(Model);
return Task.CompletedTask;
}
}

In Agnular 10 the following works:
let bar = 'Hello World!';
this._httpClient.post('api/GetDetails', '=' + bar, {
headers: new HttpHeaders({
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
})
})
PS: the way I figured it out was by comparing curls generated from dev tools for the working request in AngularJs and not working request in Angular 10

Related

Return file to download using WebAPI HTTPGet to View(User)

I am new to the Javascript side of things and I am trying to work out how to return a file to a user to download from a ApiController
ApiController:
public class TickController : ApiController
{
[Route("api/Tick/Download")]
[HttpPost]
public async Task<HttpResponseMessage> Download(string i)
{
string url = await GetURL("id00032912");
//this is hard coded until I properly work out how to get a value passed along from HttpGet
HttpResponseMessage result = null;
WebClient myClient = new WebClient();
byte[] bytes = myClient.DownloadData(url);
result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new ByteArrayContent(bytes);
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = "test" + ".txt";
return result;
}
}
Now the result is filled with the required data but I cannot manage to get it to return.
I use this call in JS to call and get to the function
await WebApi.getJSON('Tick', 'Download', ID);
This is the WebApi call expanded
static getJSON(controller: string, action: string, querystring: string, data?: any): any {
return this.get("api", controller, action, querystring, data);
}
static getODataJSON(controller: string, querystring: string, data?: any): any {
return this.get("odata", controller, null, querystring, data);
}
My Issue is Im not sure how to properly handle the value being returned in Javascript and how to force it to download on the users side. I was wondering if anyone could show some examples or point me in the right direction?
Any help would be appreciated thank you!.
NOTE I am using ApiController so I cannot use return File() like a lot of other similar questions use.

Spring Boot Post API returns null values

I've been playing around with Spring MVC and came across an issue, where I send a JSON object from the frontend with JavaScript to the backend. To do so, I use a POST Method, which seems to return null values on the backend.
JavaScript:
function calcBudget() {
var table = document.getElementById("mainTable");
const jsonBody = [];
for (var i = 1; i < table.rows.length; i++) {
const jsonItem = {};
jsonItem ["name"] = table.rows[i].cells[0].firstChild.value;
jsonItem ["category"] = table.rows[i].cells[1].firstChild.value;
jsonItem ["amount"] = table.rows[i].cells[2].firstChild.value;
jsonBody.push(jsonItem);
}
console.log(JSON.stringify(jsonBody));
var xhr = new XMLHttpRequest();
xhr.open("POST", "/home/test", true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
jsonBody
}));
}
JavaScript Output:
[{"name":"01","category":"01","amount":"03"}]
RestController:
#Controller
public class GreetingsController {
#PostMapping("/home/test")
public String readInput(#RequestBody CalcModel model) {
System.out.println(model.expenseName +" " + model.expenseCategory+" "+ model.expenseAmount);
return "index";
}
}
RestController Output:
null null null
CalcModel:
public class CalcModel {
public String expenseName;
public String expenseCategory;
public Double expenseAmount;
public CalcModel(String expenseName, String expenseCategory, Double expenseAmount) {
this.expenseName = expenseName;
this.expenseCategory = expenseCategory;
this.expenseAmount = expenseAmount;
}
}
Why is the RestController output null? I have attempted to integrate an H2 database, as I assumed I would need one. Turned out, though, that this does not work either. I also tried to use getters for the CalcModel, without any luck. Any ideas?
Edit:
It seems as I'm sending a JSON array to Spring Boot, which expects to find just a single object, not an array of objects. Removing the square brackets seems to solve the issue when testing via Postman. Now I need to find a solution how to make SpringBoot recognize the response body as a JSON array.
Solution:
Change RestController Method to this (Request Body needs to be an ArrayList)
#PostMapping("/home/test")
public String readInput(#RequestBody ArrayList<CalcModel> model) {
for (CalcModel calcModel : model) {
System.out.println(calcModel.name + " " + calcModel.category + " " + calcModel.amount);
}
return "index";
}
In the JavaScript file, remove the curly brackets
xhr.send(JSON.stringify(jsonBody));
It seems like you have different namings in the jsonBody and the CalcModel. Try changing the names to the same thing.
[{"name":"01","category":"01","amount":"03"}]
public class CalcModel {
public String name;
public String category;
public Double amount;
You might also need a parameterless constructor and getters and setters.

Print model data without saving

if (saleDetails.length) {
var htmlData;
var paymentStatus = 0;
if ($('#PaymentStatus option:selected').val() != 0) {
paymentStatus = $('#PaymentStatus option:selected').text()
}
var SaleAmount = parseFloat(total + vat).toFixed(2);
var data = {
'AccountID': $('#hdnAccountID').val(),
'QuoteID': $('#hdnQuoteID').val(),
'BranchID': $('#BranchID option:selected').val(),
'PONO': $('#PONO').val(),
'PaymentStatus': $('#PaymentStatus').val(),
'SalesDate': $('#SaleDate').val(),
'PaymentStatus': paymentStatus,
'PaymentTypeID': $('#PaymentType option:selected').val(),
'VAT': vat,
'TotalAmount': invoiceAmount,
'DiscountAmount': $('#discInput').val(),
'AmountPaid': $('#amountPaid').val(),
'SaleDetails': saleDetails
};
var json = JSON.stringify({ 'model': data });
public ActionResult printOrder(Models.DTO.Sales model)
{
return PartialView(model);
//return View(model);
}
I am working on POS , In sales client requirement is that we should give him an option of print , so that if client click on Print button we should open a new tab and show invoice , so client can take out print and if customer pay him then client will save SalesOrder.
The problem I am facing is that I am unable to open new tab from controller . And if I am trying to do this from java script I am unable to pass model to view from java script.
So please help me in this issue as I am not too much expert in MVC.
You can use Html.ActionLink to open the page in new tab from your Razor page as below.
#Html.ActionLink("Print", "Action", new { controller="PrintOrder" }, new { target="_blank" })
Html.ActionLink however does not allow you to pass complex objects. You can use trick as mentioned in this stackoverflow answer to pass your model. From the post:
MODEL: Make static Serialize and Deserialize methods in the class like
public class XYZ {
// Some Fields
public string X { get; set; }
public string Y { get; set; }
public string X { get; set; }
// This will convert the passed XYZ object to JSON string
public static string Serialize(XYZ xyz)
{
var serializer = new JavaScriptSerializer();
return serializer.Serialize(xyz);
}
// This will convert the passed JSON string back to XYZ object
public static XYZ Deserialize(string data)
{
var serializer = new JavaScriptSerializer();
return serializer.Deserialize<XYZ>(data);
}
}
VIEW: Now convert your complex object to JSON string before passing it in
Action View <%= Html.ActionLink(Model.x, "SomeAction", new { modelString = XYZ.Serialize(Model) })%>
CONTROLLER: Get the
object as string in Action method and convert it back to object before
using public ActionResult SomeAction(string modelString) { XYX xyz = XYX.Deserialize(modelString); }

How to pass json data from C# controller to angular js?

How to pass json data from C# controller to angular js ? I want to pass json from controller to angular js. I tried different but none of them worked. See my code below,
var app = angular.module('myApp', []);
app.controller('customersCtrl', function ($scope, $http) {
$http.get("/adnActions/getJson")
.success(function (response) { alert(response.records); $scope.names = response.records; });
});
C# controller code
public async Task<string> getJson()
{
data="{'records':[ {'Name':'Alfreds Futterkiste','City':'Berlin','Country':'Germany'}, {'Name':'Ana Trujillo Emparedados y helados','City':'México D.F.','Country':'Mexico'}]}";
return data;
}
but am unable to get the data in angular js controller
below is the error raised in console,
"Error: JSON.parse: expected property name or '}' at line 1 column 2 of the JSON data
how to fix this? Whats the problem here?
I suspect it is because the format of your JSON. You are using single quotes vs double. Valid JSON uses double quotes.
Here is what i get when i run your json i have changed the response to be HttpResponseMessage and explicitly set the response content type to eliminate this as an issue. Based on your error being on Javascript side i think your problem is your single quotes in your JSON.
public async Task<HttpResponseMessage> GetJsonSingle()
{
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent("{'records':[ {'Name':'Alfreds Futterkiste','City':'Berlin','Country':'Germany'}, {'Name':'Ana Trujillo Emparedados y helados','City':'México D.F.','Country':'Mexico'}]}")
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
return result;
}
results in:
While double quotes:
public async Task<HttpResponseMessage> GetJsonDouble()
{
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent("{\"records\":[ {\"Name\":\"Alfreds Futterkiste\",\"City\":\"Berlin\",\"Country\":\"Germany\"}, {\"Name\":\"Ana Trujillo Emparedados y helados\",\"City\":\"México D.F.\",\"Country\":\"Mexico\"}]}")
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
return result;
}
works correctly:
use EF to create json object and use web api controller to GET(select),PUT(update),POST(insert),DELETE(delete) data
public class CarsController : ApiController
{
private static readonly ICarRepository _cars = new CarRepository();
// GET api/<controller>
public IEnumerable<Car> Get()
{
return _cars.GetAllCars();
}
// GET api/<controller>/5
public Car Get(int id)
{
Car c = _cars.GetCar(id);
if (c == null)
throw new HttpResponseException(HttpStatusCode.NotFound);
return c;
}
// POST api/<controller>
public Car Post(Car car)
{
return _cars.AddCar(car);
}
// PUT api/<controller>/5
public Car Put(Car car)
{
if (!_cars.Update(car))
throw new HttpResponseException(HttpStatusCode.NotFound);
return car;
}
// DELETE api/<controller>/5
public Car Delete(int id)
{
Car c = _cars.GetCar(id);
_cars.Remove(id);
return c;
}
}
}

How read data sent by Client with Spark?

I have to read some data sent by Client using Spark (a framework for Java).
This is the code of client's post request. I am using jQuery.
$.post("/insertElement",
{item:item.value, value: value.value, dimension: dimension.value });
The code of server:
post(new Route("/insertElement") {
#Override
public Object handle(Request request, Response response) {
String item = (String) request.attribute("item");
String value = (String) request.attribute("value");
String dimension = (String) request.attribute("dimension");
Element e = new Element(item, value, dimension);
ElementDAO edao = new ElementDAO();
edao.insert(e);
JSONObject json = JSONObject.fromObject( e );
return json;
}
});
I am using Spark so I only have to define the route.
I would like to store in a database the data sent by client, but all the attributes are null.
I think that this way isn't correct. How can I read the sent data?
They way you send your data, using HTTP POST, you're posting the JSON as request body, not as request attributes. This means you shouldn't use request.attribute("item") and the others, but instead parse the request body to a Java object. You can use that object to create the element and store it using the DAO.
You will need something like this:
post(new Route("/insertElement") {
#Override
public Object handle(Request request, Response response) {
String body = request.body();
Element element = fromJson(body, Element.class);
ElementDAO edao = new ElementDAO();
edao.insert(e);
JSONObject json = JSONObject.fromObject( e );
return json;
}
});
public class Element {
private String item;
private String value;
private String dimension;
//constructor, getters and setters
}
public class JsonTransformer {
public static String toJson(Object object) {
return new Gson().toJson(object);
}
public static <T extends Object> T fromJson(String json, Class<T> classe) {
return new Gson().fromJson(json, classe);
}
}
try using request.queryParams("item") and so on.
Assuming this is the JSON I'm sending in my request
{ 'name': 'Rango' }
This is how I've configured my Controller to parse request body.
public class GreetingsController {
GreetingsController() {
post("/hello", ((req, res) -> {
Map<String, String> map = JsonUtil.parse(req.body());
return "Hello " + map.get("name") + "!";
})));
}
}
public class JsonUtil {
public static Map<String, String> parse(String object) {
return new Gson().fromJson(object, Map.class);
}

Categories