Make a custom method in web api and call it from angularjs - c#

I wan to make custom method in Api controller and call it from angularJS $http.(get/post).
I have a view .cshtml where i use ng-repeat to get data from database given below..
Now i want to make a custom method in web api to update only 1 field (Status=1) when admin click Approve
my Api controller is :
using AttributeRouting;
using AttributeRouting.Web.Mvc;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
namespace HRM_Project.Controllers
{
[RoutePrefix("api/EmployeeLeaveApi")]
public class EmployeeLeaveApiController : ApiController
{
private HRM27Entities db = new HRM27Entities();
// GET api/EmployeeLeaveApi
public IEnumerable<EmployeeLeave> GetEmployeeLeaves()
{
var employeeleaves = db.EmployeeLeaves.Include(e => e.Employee);
return employeeleaves.AsEnumerable();
}
// GET api/EmployeeLeaveApi/5
public EmployeeLeave GetEmployeeLeave(int id)
{
EmployeeLeave employeeleave = db.EmployeeLeaves.Find(id);
if (employeeleave == null)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
return employeeleave;
}
PUT api/EmployeeLeaveApi/5
public HttpResponseMessage PutEmployeeLeave(int id, EmployeeLeave employeeleave)
{
if (!ModelState.IsValid)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
if (id != employeeleave.LeaveID)
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
db.Entry(employeeleave).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
// POST api/EmployeeLeaveApi
public HttpResponseMessage PostEmployeeLeave(EmployeeLeave employeeleave)
{
if (ModelState.IsValid)
{
db.EmployeeLeaves.Add(employeeleave);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, employeeleave);
response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = employeeleave.LeaveID }));
return response;
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
// DELETE api/EmployeeLeaveApi/5
public HttpResponseMessage DeleteEmployeeLeave(int id)
{
EmployeeLeave employeeleave = db.EmployeeLeaves.Find(id);
if (employeeleave == null)
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}
db.EmployeeLeaves.Remove(employeeleave);
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
}
return Request.CreateResponse(HttpStatusCode.OK, employeeleave);
}
// [Route("Api/goals/update/{id}")]
[HttpGet]
[Route("Api/EmployeeLeaveApi/ApproveLeave/{id}")]
public string ApproveLeave(int id, EmployeeLeave obj)
{
var leaveIdFound = db.EmployeeLeaves.FirstOrDefault(x => x.LeaveID == id);
if (leaveIdFound != null)
{
leaveIdFound.Status = obj.Status;
db.SaveChanges();
return "Customer updated successfully!";
}
return "Customer updated fails!";
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}
I also installed AttributeRouting package.
But when i test the using "http://localhost:30429/Api/EmployeeLeaveApi/ApproveLeave/" link i got error! Error:
{"Message":"An error has occurred.","ExceptionMessage":"Multiple
actions were found that match the request:
\r\nHRM_Project.EmployeeLeave GetEmployeeLeave(Int32) on t....
I just wanna push a query like that
update leaveTable set status="1" where Leaveid=12"
others field will be remined unchanged.
,how can do this?
Anyone one tell how can i make and use a custome web api method from angular?
cshtml :
<a href="" ng-click="approveLeave(item.LeaveID)"
JS file:
$scope.approveLeave = function (a) {
$http.put('http://localhost:30429/api/employeeleaveApi/' + a)
.success(function (data) {
console.log("inserted succes");
}).error(function () {
});

Related

Why Visual Studio automatically creates ApiController with all async methods? How to create ApiController with sync methods in it?

I have created a asp.net core webapi controller named StudentsController.cs using the functionality provided by Visual Studio which is API Controller with actions,using Entity Framework. It implements all the controller methods with return type async Task<ActionResult<>> which is asynchronous method implementation and it is auto generated by Visual Studio
Question is Why it creates all the methods async by its own and how can I create all the methods synchronously using the same auto generate feature of Visual Studio?
async example of controller
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Students.Models;
namespace Students.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class StudentsController : ControllerBase
{
private readonly StudentContext _context;
public StudentsController(StudentContext context)
{
_context = context;
}
// GET: api/Students
[HttpGet]
public async Task<ActionResult<IEnumerable<Student>>> GetStudents()
{
return await _context.Students.Include(d => d.Department).ToListAsync();
}
// GET: api/Students/5
[HttpGet("{id}")]
public async Task<ActionResult<Student>> GetStudent(int id)
{
var student = await _context.Students.Include(d => d.Department).FirstOrDefaultAsync(i => i.SId == id);
if (student == null)
{
return NotFound();
}
return student;
}
// PUT: api/Students/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://aka.ms/RazorPagesCRUD.
[HttpPut("{id}")]
public async Task<IActionResult> PutStudent(int id, Student student)
{
if (id != student.SId)
{
return BadRequest();
}
_context.Departments.Update(student.Department);
await _context.SaveChangesAsync();
_context.Entry(student).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!StudentExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return Ok();
}
//[HttpPut]
//public async Task<IActionResult> PutStudent(Student student)
//{
// _context.Departments.Update(student.Department);
// await _context.SaveChangesAsync();
// _context.Entry(student).State = EntityState.Modified;
// try
// {
// await _context.SaveChangesAsync();
// }
// catch (DbUpdateConcurrencyException)
// {
// if (!StudentExists(student.SId))
// {
// return NotFound();
// }
// else
// {
// throw;
// }
// }
// return Ok();
//}
// POST: api/Students
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://aka.ms/RazorPagesCRUD.
[HttpPost]
public async Task<ActionResult<Student>> PostStudent(Student student)
{
_context.Students.Add(student);
await _context.SaveChangesAsync();
return CreatedAtAction("GetStudent", new { id = student.SId }, student);
}
[HttpPost]
[Route("StudentList")]
public async Task<ActionResult<Student>> PostStudentList([FromBody] List<Student> student)
{
try
{
foreach (Student s in student)
{
_context.Students.Add(s);
}
_context.SaveChanges();
return CreatedAtAction("GetStudents", student, _context.Students.Include(d => d.Department));
}
catch(Exception ex)
{
return BadRequest();
}
}
// DELETE: api/Students/5
[HttpDelete("{id}")]
public async Task<ActionResult<Student>> DeleteStudent(int id)
{
var student = await _context.Students.FindAsync(id);
if (student == null)
{
return NotFound();
}
_context.Students.Remove(student);
await _context.SaveChangesAsync();
return student;
}
private bool StudentExists(int id)
{
return _context.Students.Any(e => e.SId == id);
}
}
}
sync example of controller
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CourseCRUD.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace CourseCRUD.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class SubjectController : Controller
{
private readonly CourseContext _context;
public SubjectController(CourseContext context)
{
_context = context;
}
[HttpGet]
// GET:api/subject
public IActionResult GetSubjects()
{
try
{
var subjects = _context.subjects.ToList();
return Ok(subjects);
}
catch
{
return BadRequest();
}
}
[HttpPost]
public IActionResult AddSubject([FromBody]Subject subject)
{
try
{
_context.subjects.Add(subject);
_context.SaveChanges();
return CreatedAtAction("GetSubjets", subject);
}
catch
{
return BadRequest();
}
}
[HttpGet("{id}")]
public IActionResult GetSuject(int id)
{
try
{
var subject = _context.subjects.Find(id);
return Ok(subject);
}
catch
{
return BadRequest();
}
}
[HttpPut("id")]
[HttpPut("{id}")]
public IActionResult UpdateSubject(int id, Subject subject)
{
if (id != subject.SubjectId)
{
return BadRequest();
}
_context.Entry(subject).State = EntityState.Modified;
try
{
_context.SaveChanges();
return Ok(subject);
}
catch (DbUpdateConcurrencyException)
{
if (!SubjectDetailExist(id))
{
return NotFound();
}
else
{
throw;
}
}
}
private bool SubjectDetailExist(int id)
{
throw new NotImplementedException();
}
[HttpDelete("{id}")]
public IActionResult DeleteSubject(int id)
{
var result = _context.subjects.Find(id);
if (result == null)
{
return NotFound();
}
_context.subjects.Remove(result);
try
{
_context.SaveChanges();
return Ok(result);
}
catch
{
return BadRequest();
}
}
}
}```
it's a long time since I did anything with t4 templates so a bit rusty but you should perhaps start here
https://learn.microsoft.com/en-us/visualstudio/modeling/code-generation-and-t4-text-templates?view=vs-2019
You specify templates in text files and use rules to generate the required code.
<## output extension=".cs" #>
<## assembly name="System.Xml" #>
<#
System.Xml.XmlDocument configurationData = ...; // Read a data file here.
#>
namespace Fabrikam.<#= configurationData.SelectSingleNode("jobName").Value #>
{
... // More code here.
}
Depending on the values in the XML file, the generated .cs file would resemble the following:
namespace Fabrikam.FirstJob
{
... // More code here.
}
I don't know if controller scaffolding uses t4 templates but it wouldn't suprise me.. or something similar.
The async actions are generated by templates of scaffolding which locates in path similar to C:\ProgramFiles\dotnet\sdk\NuGetFallbackFolder\microsoft.visualstudio.web.codegenerators.mvc\2.0.3\Templates
You could change the template manually.Refer to
https://stackoverflow.com/a/39503291/10158551

API only returns responses with no content

My methods only return responses with no content.
Controller
[HttpGet("Floors/{floorId}", Name = "FloorById")]
public IActionResult GetFloor(int floorId)
{
try
{
Floor floor = _repository.Floor.GetFloor(floorId);
if (floor == null)
return NotFound();
return Ok(floor);
}
catch (Exception e)
{
return StatusCode(500, "text");
}
}
Repository
public Floor GetFloor(int floorId)
{
return _context.Floors.FirstOrDefault(f => f.Id == floorId);
}
Ideally, this code should return an Ok response with the object as well.
Instead, I only get an Ok response when using swagger. Not even the NotFound.
Swagger is unable to determine what type the action returns based on the IActionResult.
Use the ProducesResponseType attribute:
[ProducesResponseType(typeof(Floor), 200)] // <-- THIS
[HttpGet("Floors/{floorId}", Name = "FloorById")]
public IActionResult GetFloor(int floorId) {
try {
Floor floor = _repository.Floor.GetFloor(floorId);
if (floor == null)
return NotFound();
return Ok(floor);
} catch (Exception e) {
return StatusCode(500, "text");
}
}

How do I resolve this ASP.NET MVC 5 HTTP Error that occurs for a specific page?

I understand that this general question has been asked and answered on here many times. Initially, this problem occurred for all of my web pages. I probably tried 15 different suggested fixes on here. Eventually using a response to a similar question, I ticked the 'Override application root URL' and now my homepage and the about page load correctly. However, the problem persists for my 'Movies' and 'Ratings' pages which are almost the same, which means it's most likely the code. I am obviously missing something and I'm very new to using c#, so I would greatly any help!
This is the error:
Server Error in '/' Application. The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its
dependencies) could have been removed, had its name changed, or is
temporarily unavailable. Please review the following URL and make
sure that it is spelled correctly.
Requested URL: /Movies
Here is my Movies controller:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using AllMovies.DAL;
using AllMovies.Models;
namespace AllMovies.Controllers
{
public class MoviesController : ApiController
{
private AllMoviesContext db = new AllMoviesContext();
// GET: api/Movies
public IQueryable<MovieDTO> GetMovies()
{
var movies = from m in db.Movies
select new MovieDTO()
{
Id = m.Id,
Name = m.Name,
Genre = m.Genre,
Budget = m.Budget,
Overview = m.Overview,
release_date = m.release_date,
Ratings = m.Ratings.Select(r => new RatingDTO()
{
Id = r.Id,
userId = r.userId,
rating_score = r.rating_score
}
).ToList()
};
return movies;
}
// GET: api/Movies/5
[ResponseType(typeof(MovieDTO))]
public async Task<IHttpActionResult> GetMovies(int id)
{
Movie m = await db.Movies.FindAsync(id);
if (m == null)
{
return NotFound();
}
MovieDTO movie = new MovieDTO
{
Id = m.Id,
Name = m.Name,
Genre = m.Genre,
Budget = m.Budget,
Overview = m.Overview,
release_date = m.release_date,
Ratings = m.Ratings.Select(r => new RatingDTO()
{
Id = r.Id,
userId = r.userId,
rating_score = r.rating_score
}
).ToList()
};
return Ok(movie);
}
// PUT: api/Movies/5
[ResponseType(typeof(void))]
public async Task<IHttpActionResult> PutMovies(int id, Movie movie)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != movie.Id)
{
return BadRequest();
}
db.Entry(movie).State = EntityState.Modified;
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
// POST: api/Movies
[ResponseType(typeof(Movie))]
public async Task<IHttpActionResult> PostMovies(Movie movie)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Movies.Add(movie);
await db.SaveChangesAsync();
return CreatedAtRoute("DefaultApi", new { id = movie.Id }, movie);
}
// DELETE: api/Movies/5
[ResponseType(typeof(Movie))]
public async Task<IHttpActionResult> DeleteMovie(int id)
{
Movie movie = await db.Movies.FindAsync(id);
if (movie == null)
{
return NotFound();
}
db.Movies.Remove(movie);
await db.SaveChangesAsync();
return Ok(movie);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool MovieExists(int id)
{
return db.Movies.Count(e => e.Id == id) > 0;
}
}
}

Can't access to my method delete of my api rest

I'm not able to access to my delete method of my api rest.
If i write the method like this it work:
[Route("api/Document/{documentId:int}")]
[HttpDelete]
public IHttpActionResult Delete([FromUri]int documentId,[FromBody] int [] documentsId)
{
try
{
documentCtrl = documentCtrl ?? new DocumentCtrl();
return Ok(documentCtrl.Delete(documentsId));
}
catch (DocumentNotFoundException)
{
return NotFound();
}
catch (Exception)
{
return InternalServerError();
}
}
It works, but if i put:
[Route("api/Document/MassiveDelete")]
[HttpDelete]
public IHttpActionResult MassiveDelete([FromBody] int[] ids)
{
try
{
documentCtrl = documentCtrl ?? new DocumentCtrl();
return Ok(documentCtrl.MassiveDelete(ids));
}
catch (DocumentNotFoundException)
{
return NotFound();
}
catch (Exception)
{
return InternalServerError();
}
}
I don't have acces, any ideas what could it be?
This is my request code:
DeleteDocument(id: number): Observable<boolean> {
return this._httpService.delete(AppModule.service + 'Document/' + id, AppModule.options)
.map((response: Response) => <boolean>response.json())
.catch(this.handleError);
}//This work if i want to delete one
DeleteDocuments2(ids:Array<number>):Observable<boolean>{
AppModule.options.body=ids;
return this._httpService.delete(AppModule.service + 'Document/MassiveDelete', AppModule.options)
.map((response: Response) => <boolean>response.json())
.catch(this.handleError);
}
You cannot send two parameters in your Api, you need to createa custom class like follow and send as follows,
MyCustomRequest {
public int[] documentIds;
public int documentId;
}
and then,
public IHttpActionResult MassiveDelete([FromBody] MyCustomRequest request)
you can access it as,
request.documentIds;
request.documentId;

MVC 4 return JSON as ActionResult

i'm trying to get my apicontroller to work. But somehow i cannot return Json().
Here's the error message from the compiler:
Error CS0029 Cannot implicitly convert type
'System.Web.Http.Results.JsonResult<>'
to
'System.Web.Mvc.JsonResult' Opten.Polyglott.Web D:\Development\git\Opten.Polyglott\src\Opten.Polyglott.Web\Controllers\NewsletterApiController.cs
I cannot explain why it cannot convert the Json() to the ActionResult even the Json()inherits ActionResult.
Here's my controller:
using MailChimp;
using MailChimp.Helper;
using Opten.Polyglott.Web.Models;
using Opten.Umbraco.Common.Extensions;
using System.Configuration;
using System.Web.Mvc;
using Umbraco.Core.Logging;
using Umbraco.Web.WebApi;
namespace Opten.Polyglott.Web.Controllers
{
public class NewsletterApiController : UmbracoApiController
{
public ActionResult Subscribe(Newsletter newsletter)
{
bool isSuccessful = false;
if (ModelState.IsValid)
{
isSuccessful = SubscribeEmail(newsletter.Email);
}
return Json(new { isSuccess = isSuccessful });
}
}
}
Thanks for any help.
Your problem is within the usings as the UmbracoApiController most likely inherits from ApiController (from System.Web.Http) not Controller (from System.Web.Mvc) and thus they have different dependencies. To fix your problem first remove the
using System.Web.Mvc;
and put the
using System.Web.Http;
as for the return in this case that would be IHttpActionResult so you would have something as follows:
using MailChimp;
using MailChimp.Helper;
using Opten.Polyglott.Web.Models;
using Opten.Umbraco.Common.Extensions;
using System.Configuration;
using System.Web.Http;
using Umbraco.Core.Logging;
using Umbraco.Web.WebApi;
namespace Opten.Polyglott.Web.Controllers
{
public class NewsletterApiController : UmbracoApiController
{
public IHttpActionResult Subscribe(Newsletter newsletter)
{
bool isSuccessful = false;
if (ModelState.IsValid)
{
isSuccessful = SubscribeEmail(newsletter.Email);
}
return Json(new { isSuccess = isSuccessful });
}
}
}
Let me know if that works for you.
It seems your Json is using class in System.Web.Http, not in System.Web.Mvc. In this case, you can use this code:
return new JsonResult{ isSuccess = isSuccessful };
When using ActionResult using Response.StatusCode is a good practice:
public ActionResult SomeMethod()
{
try
{
// ...
// doing something here...
// ...
// success:
Response.StatusCode = (int)HttpStatusCode.OK;
return Json(new { responseText = "OK" });
}
catch
{
// error:
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(new { responseText = "ERROR" });
}
}
Add the following line in your WebApiConfig.cs file:
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));

Categories

Resources