How to send a string value to a function (ng-click) - angularjs

I've got a very simple questions;
Here's my HTML;
<button ng-click="projectTypeController.deleteProjectType(pt.Code)">X</button>
And my function in my controller:
self.deleteProjectType = function (projectTypeCode) {
$http.post('http://localhost:49165/Service1.svc/projecttypes/delete/', projectTypeCode)
.then(getProjectTypes)
.then(function (response) {
});
};
Code in my webservice:
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "ProjectTypes/Delete/", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
void DeleteProjectType(string projectTypeCode);
This works perfectly fine as long as 'pt.Code' is numeric, but as soon as it's a string it results in a HTTP 400 Bad Request. So I think i'm doing something wrong with the deleteProjectType(pt.Code) Part.
I tried to look for examples where they pass a string into a method, but i cannot find anything...
the pt.Code = a scope variable by the way, also adding data in the form of object inside a form element works fine, so passing strings in an object is not a problem, just passing a single string, instead of an integer to a method doesn't seem to work

You need to format the parameter as a valid json.
To do that you can use JSON.stringify().
To implementet this in the method
self.deleteProjectType = function (projectTypeCode) {
$http.post('http://localhost:49165/Service1.svc/projecttypes/delete/', JSON.stringify(projectTypeCode))
.then(getProjectTypes)
.then(function (response) {
});
};
I prefere to use objects instead of just sending a value as a string.
If you at any time need to extend the body then you only need to add more fields to the objects and not modify the function call or the service method.
Here's an example of how you could do that
self.deleteProjectType = function (projectTypeCode) {
var data = { code: projectTypeCode};
$http.post('http://localhost:49165/Service1.svc/projecttypes/delete/', JSON.stringify(data))
.then(getProjectTypes)
.then(function (response) {
});
};
Create the class server side
Public class ProjectTypeDTO
{
public string code { get; set; }
}
Add the class as the parameter in the service method and you are gtg
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "ProjectTypes/Delete/", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
void DeleteProjectType(ProjectTypeDTO pt);

Related

Byte array and JSON in [FromBody]

I am trying pass an object which consists of different data type. I am always getting null value for orderDetails in Web API.
However if do this,
purchaseOrder.Attachments = null,
in the client then orderDetails is no longer null and I have other informations like "SendEmail" and PurchaseOrderNumber.
It looks I might not be correctly set the parameter in the client (angular 2).
However testing the same Web Api method from Console app works fine and I am not getting a null value.
Do I need to separate the JSON data and byte array?
regards,
-Alan-
Models
public class Attachments
{
public int AttachmentId { get; set; }
public string FileName { get; set ;}
public byte[] FileData { get; set ;}
}
public class UpdatePurchaseOrderViewModel
{
public bool SendEmail { get; set; }
public int PurchaseOrderNumber { get; set; }
public Attachments Attachments { get; set;
}
Here is my Web API put method definition
[HttpPut("AddPurchaseOrderNumber/{purchaseOrderId}")]
public StatusCodeResult AddPurchaseOrderNumber(int purchaseOrderId, [FromBody] UpdatePurchaseOrderViewModel orderDetails)
{
try
{
var status = _service.AddPurchaseOrderNumber(purchaseOrderId, orderDetails);
if (status == 200)
_unitOfWorkAsync.SaveChanges();
else return StatusCode(status);//No Data
}
catch
{
return StatusCode(400); // Bad Request
}
return StatusCode(200);//OK
}
Typescript snippet
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept','application/json');
let options = new RequestOptions({ headers: headers });
var body = JSON.stringify(
purchaseOrder
);
var uri = 'http://localhost:33907/api/purchaseorder/addpurchaseordernumber/' + purchaseOrderId;
return this._http.put(uri, body , options)
.map((response: Response) => {
let data = response.json();
if (data) {
return true;
}
else {
return false;
}
})
Update
The orderDetails is created as below
let file = Observable.create((observer) => {
let fr = new FileReader();
let data = new Blob([this.attachment]);
fr.readAsArrayBuffer(data);
fr.onloadend = () => {
observer.next(fr.result);
observer.complete();
};
fr.onerror = (err) => {
observer.error(err);
}
fr.onabort = () => {
observer.error("aborted");
}
});
file.map((fileData) => {
//build the attachment object which will be sent to Web API
let attachment: Attachments = {
AttachmentId: '0',
FileName: this.form.controls["attachmentName"].value,
FileData: fileData
}
//build the purchase order object
let order: UpdatePurchaseOrder = {
SendEmail: true,
PurchaseOrderNumber:this.form.controls["purchaseOrderNumber"].value * 1, //for casting purpose
Attachments: attachment
}
console.log("Loading completed");
return order;
})
When sending objects that have byte arrays as a property back and forth between a client to a WebAPI endpoint, I typically use a DTO that stores the property to explicitly define it as a Base64 string. On the server side I map the DTO to my entity by converting the Base64 string to / from the byte array for server side operations and storing in the database.
The serializer will do something like this automatically but the format passed from JavaScript may not match what the WebAPI JSON serializer is expecting (which is why it's working from your C# Console App).
You didn't include how you are creating the purchaseOrder object in your JavaScript so I can't comment on how that object is being setup - which may be where your issue is.

Retrieving POSTED data from controller

I'm using angular js. I posted data to a controller in vb.net from a JS file. How can I retrieve the data in the vb controller?.
Below is my app.factory method.
UpdateServiceData: function (p1, p2) {
var data = $.param({
fName: "John",
lName: "Smith"
});
var config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8;'
}
}
$http({
method: "post",
url: '../api/Service/UpdateSvcData',
data,
config,
params: {
'P1': p1,
'P2': p2
}
}
});
}
UpdateSvcData is a method inside the controller ServiceController.vb
I just need to retrieve the posted values inside ServiceController.vb
i.e., I need to get fName and lName.
In short, I'm posting values from a JS file. I need to retrieve it at the ServiceController.vb using vb.net
I tried Request.QueryString("fName"), Request.Form["fName"] etc. But these are not giving the results.
Thanks
Public Function UpdateServiceData(<FromUri()> request As ServiceEntities) As HttpResponseMessage
Dim success As Boolean = True
Dim response As HttpResponseMessage
Try
Dim dataAccess As DB.DataAccessBase = DB.DataAccessBase.GetInstance(DataAcessTypes.Service)
request.MethodName = "UpdateServiceData"
Dim sJSON As String = dataAccess.Select(Of ServiceEntities)(request)
response = Me.Request.CreateResponse(HttpStatusCode.OK)
response.Content = New StringContent(sJSON, Encoding.UTF8, "application/json")
Catch ex As Exception
response = Me.Request.CreateResponse(HttpStatusCode.InternalServerError)
End Try
Return response
End Function
You need to return the $http object to the controller if I understand your question, hard to tell without seeing the controller though.

Json array is null when received in controller

function viewReports(firstDate, lastDate) {
var selected = $('#ReportSelected').find(":selected");
var controller = "PortalReports";
var method = "GetReport";
var urlAjax = $("#basePath").val() + controller + "/" + method;
var companydropdown = $('#ReportSelected :selected').data("companydropdown");
var agencydropdown = $('#ReportSelected :selected').data("agencydropdown");
var userdropdown = $('#ReportSelected :selected').data("userdropdown");
var data =
{
reportSelected: selected.text(),
firstDate: firstDate,
lastDate: lastDate,
companydropdown: companydropdown,
agencydropdown: agencydropdown,
userdropdown: userdropdown
};
/*var data =
[{
"reportSelected": selected.text(),
"firstDate": firstDate,
"lastDate": lastDate,
"companydropdown": companydropdown,
"agencydropdown": agencydropdown,
"userdropdown": userdropdown
}];*/
var answer = JSON.stringify({ data });
$.ajax({
traditional: true,
data: JSON.stringify({ data }),
url: urlAjax,
success: function (response) {
loadReport(response);
},
error: function (ob, errStr) {
alert("An error occured. Please try again.");
}
});
//Mvc
public JsonResult GetReport(JArray data)
{
var persons = data.Select(x => x.ToObject<InputJson>());
JArray data is always null irrespective of how many ways I add square brackets of remove quotation marks etc, what am I doing wrong!!!
Prefer simple Object returned in array for readability as I might need to add to it.
Since you are sending a complex data structure(array), you should specify the contentType property when making ajax call. Specify the value of contentType property as "application/json"
//Values hard coded, you may replace with real values from your form.
var dataArray = [{
reportSelected:'201501',
firstDate: '11/12/2010',
lastDate: '12/12/2010',
companydropdown: 4,
agencydropdown: 6,
userdropdown: 16,
}];
var urlAjax = "/Home/GetReport"; // Hard coded for demo. Read further..
$.ajax({
type: "POST",
contentType: "application/json",
data: JSON.stringify(dataArray),
url: urlAjax,
success: function (response) {
console.log(response);
},
error: function (ob, errStr) {
alert("An error occured. Please try again.");
}
});
I suggest you create a view model /DTO to represent the data you are sending and use that in your action method.
public class ReportRequest
{
public string reportSelected { get; set; }
public DateTime firstDate { get; set; }
public int companydropdown { get; set; }
}
[HttpPost]
public JsonResult GetReport(IEnumerable<ReportRequest> data)
{
//do something with data
// to do : Return something
}
In the example, I hardcoded the value of urlAjax variable. You may consider using the html helper methods to generate the correct relative url path to the action method(s) as explained in this post.

Why are numbers sent from the web UI arriving in my MVC app as 'null;?

I am sending a jQuery Ajax request as such:
$scope.geo.setSuburbs2 = function(areaId) {
var idData = JSON.stringify({ 'areaId': 3, 'agentId': 1 });
$.ajax({
url: "/Area/SuburbsJson",
method: "POST",
data: idData,
dataType: "ajax"
}).then(function(idData) {
alert("Done!");
},
function(data, status) {
alert("Error: " + status);
});
};
This is supposed to fetch suburbs in ID AreaId serviced by an agent with ID agentId. The suburbs returned are key-value pairs in an array on the viewmodel. When I receive the model at the controller, all the keys are still correct in the array, but all numeric values are null.
When I send a data option from the $.ajax call that looks like:
{ 'areaId': 3, 'agentId': 1 }
I get the same size array of key-values on the web app, in OnActionExecuting in the controller, the above array item looks like:
{ 'areaId': null, 'agentId': null }
I strongly suspect a serialization problem on the browser, because the null values should not yet have arrived at my JsonDotNet custom (from the web) serializer. I normally only use that to improve serialization in POST resonses, when I send data back to the UI.
Is this some known problem, or do I have to pore through all the settings, a long list, on the JsonDotNet serializer? If it is a known problem, what should I do about it?
The viewmodel is List<CheckListItemModel>, where:
public class CheckListItemModel
{
public int Id { get; set; }
public string Label { get; set; }
public bool IsChecked { get; set; }
}
I don't use serialized viewmodels to talk between the controllers and the UI, I just pass a UI Angular controller function a filter ID for a list, and it returns the serialized list, with all numeric values set to null.
The action that sends the correct data to the UI is:
public JsonResult SuburbsJson(int areaId, int agentId)
{
var allBurbs = _areaClient.GetSuburbs(areaId).ToList();
var agentBurbIds = _agentClient.GetAgentSuburbs(agentId).Select(s => s.SuburbId).ToList();
var model = new List<CheckListItemModel>();
foreach (var burb in allBurbs)
{
model.Add(new CheckListItemModel { Id = burb.SuburbId, Label = burb.SuburbName, IsChecked = agentBurbIds.Contains(burb.SuburbId) });
}
return Json(model, JsonRequestBehavior.DenyGet);
}
It's a question of Id and IsChecked. And item is already checked if its Id is in a list of Agents associated with that SuburbId.
The JSON.stringify() method converts a JavaScript value to a JSON
string,
Recheck your payload construction. you need to stringify actual JavaScript object like...
$scope.geo.setSuburbs2 = function(areaId) {
var value = { areaId: 3, agentId: 1 }; //Object to be sent to controller
var idData = JSON.stringify(value);
$.ajax({
url: "/Area/SuburbsJson",
type: "POST",
contentType: 'application/json',
dataType: 'json',
data: idData
}).then(function(idData) {
alert("Done!");
},
function(data, status) {
alert("Error: " + status);
});
};
by removing the single quotes on the keys. Also note the changes to how the request was made to the controller.

sending HashMap by angularjs $http.get in spring mvc

I want to send and retrieve HashMap through angularjs and receive it in springmvc controller. I have successfully send and received List but unable to send HashMap.
My code is.
$scope.addskill = function(skills){
// $scope.list = [];
// $scope.list.push(skills.skillName, skills.expMonth, skills.expYear, skills.experties);
var map = {};
map['name'] = skills.skillName;
map['month'] = skills.expMonth;
map['year'] = skills.expYear;
map['experties'] = skills.experties;
alert(map['name']);
var response = $http.get('/JobSearch/user/addskill/?map=' +map);
// var response = $http.get('/JobSearch/user/addskill/?list=' +$scope.list);
response.success(function(data, status, headers, config){
$scope.skills = null;
$timeout($scope.refreshskill,1000);
});
response.error(function(data, status, headers, config) {
alert( "Exception details: " + JSON.stringify({data: data}));
});
};
My mvc Controller is :
#RequestMapping(value = "/addskill", method = RequestMethod.GET)
#ResponseStatus(value = HttpStatus.NO_CONTENT)
public void addStudentSkill(#RequestBody HashMap<String,String> map){
System.out.println(map.get("name"));
/*
* public void addStudentSkill(#RequestParam("list") List list){
try{
StudentSkills skills = new StudentSkills();
skills.setSkillName(list[0]);
skills.setExpMonth(Integer.parseInt(list[1]));
skills.setExpYear(Integer.parseInt(list[2]));
skills.setExperties(list[3]);
skills.setStudent(studentService.getStudent(getStudentName()));
studentService.addStudentSkill(skills);
}catch(Exception e){};
*/
}
Commented code works when i send and receive List. I want to use key to retrieve data. If there is any better way please suggest.
The error is cannot convert java.lang.string to hashmap
You're sending the map as a request parameter. And you're trying to read it in the request body. That can't possibly work. And GET requests don't have a body anyway.
Here's how you should do it:
var parameters = {};
parameters.name = skills.skillName;
parameters.month = skills.expMonth;
parameters.year = skills.expYear;
parameters.experties = skills.experties;
var promise = $http.get('/JobSearch/user/addskill', {
params: parameters
});
And in the Spring controller:
#RequestMapping(value = "/addskill", method = RequestMethod.GET)
#ResponseStatus(value = HttpStatus.NO_CONTENT)
public void addStudentSkill(#RequestParam("name") String name,
#RequestParam("name") String month,
#RequestParam("name") String year,
#RequestParam("name") String experties) {
...
}
That said, given the name of the method addStudentSkill, and the fact that it doesn't return anything, it seems this method is not used to get data from the server, but instead to create data on the server. So this method should be mapped to a POST request, and the data should be sent as the body:
var data = {};
data.name = skills.skillName;
data.month = skills.expMonth;
data.year = skills.expYear;
data.experties = skills.experties;
var promise = $http.post('/JobSearch/user/addskill', params);
and in the controller:
#RequestMapping(value = "/addskill", method = RequestMethod.POST)
#ResponseStatus(value = HttpStatus.CREATED)
public void addStudentSkill(#RequestBody Map<String, String> data) {
...
}

Resources