call api controller method in asp.net mvc from angularjs - asp.net-mvc

Hello i have a server side controller method:
public class CustomerController : ApiController
{
public void Delete(IList customers)
{
// handle delete action here....
}
}
I am using Angularjs , my question is how can i call my delete method from angularjs at client side.
Thanks

You could use an AJAX request with $http:
var customers = [
{ id: 1, name: 'John' },
{ id: 2, name: 'Smith' }
];
$http({
method: 'DELETE',
url: '/customer',
data: customers
}).success(function(data, status, headers, config) {
alert('success');
}).error(function(data, status, headers, config) {
alert('error');
});

You should probably use $http in angularjs rather than normal http.
function Delete(customer) {
var promise = $http.post(
'/customer',
{ customer: customer}
).success(function (data, status, headers, config) {
return data;
}).error(function (data) {
return data;
});
return promise;
}

Related

How to call async Task from ajax aspnet core

I am using asp.net core and I am calling async task ActionResult method from ajax. Its is running fine on local host but after hosting on IIS it throw 500 status code error.
But it is not calling this method is ajax code
This is ajax method:
$('.Savebtn').click(function () {
$.ajax({
url: '#Url.Action("Testing", "Home")',
data: "Test data",
type: 'POST', //POST if you want to save, GET if you want to fetch data from server
success: function (obj) {
// here comes your response after calling the server
alert('Suceeded');
},
error: function (obj) {
alert('Something happened');
}
});
});
This is Controller method:
[HttpPost]
public async Task<IActionResult> Testing()
{
if (ModelState.IsValid)
{
try
{
return NotFound();
}
catch (Exception ex)
{
return NotFound();
}
}
return View();
}
Error Screen Shot
In Startup.cs file add service like this:
services.AddAntiforgery(options => options.HeaderName = "RequestVerificationToken");
In your cshtml file add:
#Html.AntiForgeryToken()
$.ajax({
type: 'GET',
url: '/home/Demo1',
beforeSend: function (xhr) {
xhr.setRequestHeader("RequestVerificationToken",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
success: function (result) {
alert(result);
},
error: function (xhr, ajaxOptions, thrownError) {
alert(thrownError);
}
});
And your method in Controller looks like this:
[HttpGet]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Demo1()
{
//your code
return new JsonResult(null);
}
If you don't want [ValidateAntiForgeryToken] remove it and it will work. If you want it, then you have to pass the auto generated cookie value to validate as mentioned below, check this.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Testing()
{
if (ModelState.IsValid)
{
try
{
await Task.Delay(100);
return Ok();
}
catch (Exception ex)
{
return NotFound();
}
}
return View();
}
View:
#using (Html.BeginForm(null, null, FormMethod.Post, new { id = "__AjaxAntiForgeryForm" }))
{
#Html.AntiForgeryToken()
}
<button class="Savebtn btn btn-success">Save</button>
Script:
$(document).ready(function () {
$('.Savebtn').click(function () {
var form = $('#__AjaxAntiForgeryForm');
var token = $('input[name="__RequestVerificationToken"]', form).val();
$.ajax({
url: '#Url.Action("Testing", "Home")',
data: {
__RequestVerificationToken: token,
data: "Test data"
},
type: 'POST', //POST if you want to save, GET if you want to fetch data from server
success: function (obj) {
// here comes your response after calling the server
alert('Suceeded');
},
error: function (obj) {
alert('Something happened');
}
});
});
})
</script>
Reference
First change the URL to like 'Testing/Home' and Make sure you're passing data because if you don't it might throw 500 status code error.
In my case I wasn't passing any data I mean I was sending an empty form that was why. I thought it might help someone.

angular JS Put method with ASP.NET MVC

I have my angular controller defined like this for Put and Get method. I m new to angular JS. The get method works as expected but the Put method is not getting called. I followed one of the tutorial and implemented. though in the tutorial, they used REST service URL rather than controller method. I m using MVC controller here not the webAPI one.
public JsonResult GetEmployee(int id)
{
Employee empDetail = emp.GetEmployees().FirstOrDefault(i => i.EmpID == id);
return Json(empDetail, JsonRequestBehavior.AllowGet);
}
public JsonResult PutEmployee(int id, Employee updtEmp)
{
updtEmp.EmpID=id;
int index = emp.GetEmployees().FindIndex(i => i.EmpID == updtEmp.EmpID);
emp.GetEmployees().RemoveAt(index);
emp.GetEmployees().Add(updtEmp);
return Json(emp.GetEmployees(), JsonRequestBehavior.AllowGet);
}
Here is my angular Factory and controller method
myservice.factory('empFactory', function ($resource) {
return $resource('../../Employee/GetEmployee/:EmpID', { EmpID: '#EmpID' },
{
show: { method: 'GET' },
update: { method: 'PUT', params: { Employee: '#employee' } }
});
});
myApp.controller('empDetailController', function ($scope, empFactory, $routeParams) {
$scope.Employee = empFactory.show({ EmpID: $routeParams.EmpID });
$scope.UpdateEmp = function () {
// alert($scope.Employee.FirstName);
var employee=$scope.Employee;
empFactory.update({ EmpID: $routeParams.EmpID, Employee: employee })
};
});
Where did you mention in the MVC controller the method is PUT, Until and unless you mention the method type HttpPut or HttpPost etc., they are treated as HttpGet, Mention the method as PUT method in your MVC controller and try again.
Decorate your MVC PUT method like this :
[HttpPut]
public JsonResult PutEmployee(int id, Employee updtEmp)
{
updtEmp.EmpID=id;
int index = emp.GetEmployees().FindIndex(i => i.EmpID == updtEmp.EmpID);
emp.GetEmployees().RemoveAt(index);
emp.GetEmployees().Add(updtEmp);
return Json(emp.GetEmployees(), JsonRequestBehavior.AllowGet);
}
and factory and controller shouldbe like this :
myservice.factory('empFactory', function ($resource) {
var resource = {
employees:$resource('../../Employee/GetEmployee/:EmpID', { EmpID: '#EmpID' }),
empUpdateService:$resource('../../Employee/PutEmployee/:EmpID', { EmpID: '#EmpID' },{
update: { method: 'PUT', params: { Employee: '#employee' } }
})
};
return resource;
});
myApp.controller('empDetailController', function ($scope, empFactory, $routeParams) {
$scope.Employee = empFactory.employees.get({ EmpID: $routeParams.EmpID });
$scope.UpdateEmp = function () {
// alert($scope.Employee.FirstName);
var employee=$scope.Employee;
empFactory.empUpdateService.update({ EmpID: $routeParams.EmpID, Employee: employee })
};
You wanted to do it in a very good way, but for that you should use WEB Api controllers.
Web Api controller should be like this :
public class Employee : ApiController
{
public EmpModel GetEmployee(int id)
{
Employee empDetail = emp.GetEmployees().FirstOrDefault(i => i.EmpID == id);
return empDetail;
}
public bool PutEmployee(int id, Employee updtEmp)
{
updtEmp.EmpID=id;
int index = emp.GetEmployees().FindIndex(i => i.EmpID == updtEmp.EmpID);
emp.GetEmployees().RemoveAt(index);
emp.GetEmployees().Add(updtEmp);
return emp.PutEmployees(updtEmp);
}
public bool PostEmployee(Employee empModel)
{
// do something
return emp.SaveEmployees(empModel);
}
public bool DeleteEmployee(int id)
{
// do something
return emp.DeleteEmployees(id);
}
}
consider the below resource, that can do four operations. they are get, post, put and delete. :
var resource = {
employee: $resource('../../Employee/:EmpID', { EmpID: '#EmpID' },
{
update: { method: 'PUT' },
});
}
return resource;
use your resource in controllers like this, for get :
$scope.Employee = empFactory.employee.get({ EmpID: $routeParams.EmpID }).$promise;
for post :
$scope.SaveEmp = function (employee) {
empFactory.employee.save({
EmpID: $routeParams.EmpID,
Employee: employee
}, function (response) {
// do something with your success response
})
};
for Delete :
$scope.UpdateEmp = function () {
empFactory.employee.delete({
EmpID: $routeParams.EmpID
}, function (response) {
// do something with your success response
})
};
for update :
$scope.UpdateEmp = function (employee) {
empFactory.employee.update({
EmpID: $routeParams.EmpID,
Employee: employee
}, function (response) {
// do something with your success response
})
};
This is my service with multiple resource statements. Its close what you have initially shared as well
var resource = {
employee:
$resource('../../Employee/GetEmployee/:EmpID', { EmpID: '#EmpID' },
{
show: { method: 'GET' }
}),
empUpdate:
$resource('../../Employee/PutEmployee/:EmpID', { EmpID: '#EmpID', empval: '#empl' }, { update: { method: 'PUT', isArray: true } }),
empDelete:
$resource('../../Employee/DeleteEmployee/:EmpID', { EmpID: '#EmpID' }, { del: { method: 'DELETE', isArray: true } }),
empCreate:
$resource('../../Employee/CreateEmployee', { empval: '#empl' }, { create: { method: 'POST', isArray: true } })
}
return resource;
Now i have another problem that my angular js views are not updating and i posted it in stackoverflow. if you help it would be great
Angular JS CRUD update not refreshing

sending data to MVC from an angular post

We are using angularjs to post a form to an MVC controller to process
$scope.resultsFilter = function () {
$scope.data = [];
$scope.data = {
startdate: $scope.$$childHead.resultfilter.startdate,
enddate: $scope.$$childHead.resultfilter.enddate,
frequency: $scope.resultfilter.frequency,
direction: $scope.resultfilter.direction
};
var url = '/user/GetResults/';
$http.post(url, $scope.data).success(function (data, status, headers, config) {
if (data.msg != '') {
$scope.msgs.push(data.msg);
}
else {
$scope.errors.push(data.error);
}
}).error(function (data, status) { // called asynchronously if an error occurs
// or server returns response with an error status.
$scope.errors.push(status);
});
};
});
and the MVC controller is :-
[HttpPost]
public ActionResult GetResults()
{
}
how do we access the data that has been posted by the form?
If you have POCO equivalent of that data, something like:
public class MyData{
public DateTime startdate{get;set;}
public DateTime enddate{get;set;}
....
}
You can try:
[HttpPost]
public ActionResult GetResults(MyData myData)
{
}
With the following HTTP Post:
$http({
url: '/controllerName/GetResults/',
method: "POST",
data:$scope.data,
})
.success(function (data, status, headers, config) {
}).error(function (data, status, headers, config) {
});
you can get MVC model using model object and pass to function as json
data
click=someFunc('#Json.Encode(Model)');

MVC: pass parameter to action using Jquery.ajax()

I'm pretty new to MVC. I need to make ajax call to an Action with parameters using html.Action(). I'm unable to pass this..
Hope it will be helpful for other MVC begineers as well..
HTML:
<%: Html.ActionLink("Add Race", "AddRace",
new {eventId = Model.EventId, fleetId=Model.SelectedFleet.ID},
new{#onclick=string.Format("return checkFleetAddedandScroing()")}) %>
Jquery:
function checkFleetAddedandScroing() {
debugger;
$.ajax({
type: "GET",
url: '<%=Url.Action("CheckFleetExists")%>',
dataType: "json",
cache: false,
success: function (data, textStatus) {
data = eval("(" + data + ")");
if (data == true) {
return true;
}
else {
alert("Cannot Add race becasue you have not yet added any fleets and fleet scoring is checked.");
return false;
}
}, //success
error: function (req) {
}
});
}
Action:
public JsonResult CheckFleetExists(Guid fleetId )
{
bool exists = false;
try
{
exists = !db.Races.Any(r => r.FleetID == fleetId);
}
catch
{
}
return Json(exists, JsonRequestBehavior.AllowGet);
}
I need to pass fleetid to action which is in Model.SelectedFleet.ID. Its being used somewhere on pages. But i'm unable to use that somehow..
please suggest where i'm doing wrong...
It looks like you are trying to invoke a controller action using AJAX when the link is clicked and depending on the result of this call either allow the user to be redirected to the actual AddRace action or be prompted with an error message.
The problem with your code is that you are attempting to return true/false from within the success AJAX callback which doesn't make any sense. You need to always return false from the click callback and inside the success callback, depending on the returned value from the server, redirect manually using the window.location.href function.
HTML:
<%: Html.ActionLink(
"Add Race",
"AddRace",
new {
eventId = Model.EventId,
fleetId = Model.SelectedFleet.ID
},
new {
data_fleetid = Model.SelectedFleet.ID,
#class = "addRace"
}
) %>
Jquery:
<script type="text/javascript">
$(function () {
$('.addRace').click(function (evt) {
$.ajax({
type: 'GET',
url: '<%= Url.Action("CheckFleetExists") %>',
cache: false,
data: { fleetId: $(this).data('fleetid') },
success: function (data) {
if (data.exists) {
// the controller action returned true => we can redirect
// to the original url:
window.location.href = url;
}
else {
alert("Cannot Add race becasue you have not yet added any fleets and fleet scoring is checked.");
}
},
error: function (req) {
}
});
// we make sure to cancel the default action of the link
// because we will be sending an AJAX call
return false;
});
});
</script>
Action:
public ActionResult CheckFleetExists(Guid fleetId)
{
bool exists = false;
try
{
exists = !db.Races.Any(r => r.FleetID == fleetId);
}
catch
{
}
return Json(new { exists = exists }, JsonRequestBehavior.AllowGet);
}
Remark: inside your AddRace controller action don't forget to perform the same verification as you are doing inside your CheckFleetExists. The user could simply disable javascript and the AJAX call will never be done.
change your action like this :
public JsonResult CheckFleetExists(string fleetId)
{
var fleetGuid = Guid.Parse(fleetId);
bool exists = false;
try
{
exists = !db.Races.Any(r => r.FleetID == fleetGuid );
}
catch
{
}
return new JsonResult{ Data = exists};
}
and change you ActionLink so :
<%: Html.ActionLink("Add Race", "AddRace",
new {eventId = Model.EventId, fleetId=Model.SelectedFleet.ID},
new{onclick=string.Format("return checkFleetAddedandScroing({0})",Model.SelectedFleet.ID)}) %>
and your script block may look something like this :
function checkFleetAddedandScroing($fleetId) {
$.ajax({
type: "POST",
url: '<%=Url.Action("CheckFleetExists")%>',
dataType: "json",
data : { "fleetId" : $fleetId },
cache: false,
success: function (data, textStatus) {
data = eval("(" + data + ")");
if (data == true) {
return true;
}
else {
alert("Cannot Add race becasue you have not yet added any fleets and fleet scoring is checked.");
return false;
}
}, //success
error: function (req) {
}
});
}
Problem was in answers that url to action was not complete..i did it using this way
function checkFleetAddedandScroing() {
// debugger;
$.ajax({
type: "POST",
url: '<%=Url.Action("CheckFleetExists", new {eventId=Model.EventId})%>',
dataType: "json",
cache: false,
success: function (data, textStatus) {
data = eval("(" + data + ")");
if (data == true) {
return true;
}
else {
alert("Cannot Add race becasue you have not yet added any fleets and fleet scoring is checked.");
return false;
}
}, //success
error: function (req) {
}
});
}

ASP.NET MVC Ajax Error handling

How do I handle exceptions thrown in a controller when jquery ajax calls an action?
For example, I would like a global javascript code that gets executed on any kind of server exception during an ajax call which displays the exception message if in debug mode or just a normal error message.
On the client side, I will call a function on the ajax error.
On the server side, Do I need to write a custom actionfilter?
If the server sends some status code different than 200, the error callback is executed:
$.ajax({
url: '/foo',
success: function(result) {
alert('yeap');
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert('oops, something bad happened');
}
});
and to register a global error handler you could use the $.ajaxSetup() method:
$.ajaxSetup({
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert('oops, something bad happened');
}
});
Another way is to use JSON. So you could write a custom action filter on the server which catches exception and transforms them into JSON response:
public class MyErrorHandlerAttribute : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
filterContext.ExceptionHandled = true;
filterContext.Result = new JsonResult
{
Data = new { success = false, error = filterContext.Exception.ToString() },
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
}
and then decorate your controller action with this attribute:
[MyErrorHandler]
public ActionResult Foo(string id)
{
if (string.IsNullOrEmpty(id))
{
throw new Exception("oh no");
}
return Json(new { success = true });
}
and finally invoke it:
$.getJSON('/home/foo', { id: null }, function (result) {
if (!result.success) {
alert(result.error);
} else {
// handle the success
}
});
After googling I write a simple Exception handing based on MVC Action Filter:
public class HandleExceptionAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest() && filterContext.Exception != null)
{
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
filterContext.Result = new JsonResult
{
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = new
{
filterContext.Exception.Message,
filterContext.Exception.StackTrace
}
};
filterContext.ExceptionHandled = true;
}
else
{
base.OnException(filterContext);
}
}
}
and write in global.ascx:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleExceptionAttribute());
}
and then write this script on the layout or Master page:
<script type="text/javascript">
$(document).ajaxError(function (e, jqxhr, settings, exception) {
e.stopPropagation();
if (jqxhr != null)
alert(jqxhr.responseText);
});
</script>
Finally you should turn on custom error.
and then enjoy it :)
Unfortunately, neither of answers are good for me. Surprisingly the solution is much simpler. Return from controller:
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, e.Response.ReasonPhrase);
And handle it as standard HTTP error on client as you like.
I did a quick solution because I was short of time and it worked ok. Although I think the better option is use an Exception Filter, maybe my solution can help in the case that a simple solution is needed.
I did the following. In the controller method I returned a JsonResult with a property "Success" inside the Data:
[HttpPut]
public JsonResult UpdateEmployeeConfig(EmployeConfig employeToSave)
{
if (!ModelState.IsValid)
{
return new JsonResult
{
Data = new { ErrorMessage = "Model is not valid", Success = false },
ContentEncoding = System.Text.Encoding.UTF8,
JsonRequestBehavior = JsonRequestBehavior.DenyGet
};
}
try
{
MyDbContext db = new MyDbContext();
db.Entry(employeToSave).State = EntityState.Modified;
db.SaveChanges();
DTO.EmployeConfig user = (DTO.EmployeConfig)Session["EmployeLoggin"];
if (employeToSave.Id == user.Id)
{
user.Company = employeToSave.Company;
user.Language = employeToSave.Language;
user.Money = employeToSave.Money;
user.CostCenter = employeToSave.CostCenter;
Session["EmployeLoggin"] = user;
}
}
catch (Exception ex)
{
return new JsonResult
{
Data = new { ErrorMessage = ex.Message, Success = false },
ContentEncoding = System.Text.Encoding.UTF8,
JsonRequestBehavior = JsonRequestBehavior.DenyGet
};
}
return new JsonResult() { Data = new { Success = true }, };
}
Later in the ajax call I just asked for this property to know if I had an exception:
$.ajax({
url: 'UpdateEmployeeConfig',
type: 'PUT',
data: JSON.stringify(EmployeConfig),
contentType: "application/json;charset=utf-8",
success: function (data) {
if (data.Success) {
//This is for the example. Please do something prettier for the user, :)
alert('All was really ok');
}
else {
alert('Oups.. we had errors: ' + data.ErrorMessage);
}
},
error: function (request, status, error) {
alert('oh, errors here. The call to the server is not working.')
}
});
Hope this helps. Happy code! :P
In agreement with aleho's response here's a complete example. It works like a charm and is super simple.
Controller code
[HttpGet]
public async Task<ActionResult> ChildItems()
{
var client = TranslationDataHttpClient.GetClient();
HttpResponseMessage response = await client.GetAsync("childItems);
if (response.IsSuccessStatusCode)
{
string content = response.Content.ReadAsStringAsync().Result;
List<WorkflowItem> parameters = JsonConvert.DeserializeObject<List<WorkflowItem>>(content);
return Json(content, JsonRequestBehavior.AllowGet);
}
else
{
return new HttpStatusCodeResult(response.StatusCode, response.ReasonPhrase);
}
}
}
Javascript code in the view
var url = '#Html.Raw(#Url.Action("ChildItems", "WorkflowItemModal")';
$.ajax({
type: "GET",
dataType: "json",
url: url,
contentType: "application/json; charset=utf-8",
success: function (data) {
// Do something with the returned data
},
error: function (xhr, status, error) {
// Handle the error.
}
});
Hope this helps someone else!
For handling errors from ajax calls on the client side, you assign a function to the error option of the ajax call.
To set a default globally, you can use the function described here:
http://api.jquery.com/jQuery.ajaxSetup.

Resources