Reputation: 309
I've seen a few other posts on this, but I have yet to find one that will fix my particular situation. I am trying to return a JSON object of my Entity Framework generated model class. Here is my view:
@{
ViewBag.Title = "Clock In/Out";
var currentEmployee = ViewBag.CurrentEmployee;
var existingTimeEntry = ViewBag.ExistingTimeEntry;
var btnValue = "";
var btnClass = "";
btnValue = currentEmployee.IsClockedIn == true ? "Clock Out" : "Clock In";
btnClass = currentEmployee.IsClockedIn == true ? "clock-out-btn" : "clock-in-btn";
}
<header class="login-header">
<div class="clearfix">
<h1>@ViewBag.Title</h1>
</div>
</header>
@{
using (Html.BeginForm(null, null, FormMethod.Post, new { id = "clock-in-form" }))
{
@Html.AntiForgeryToken()
<div class="clock-in-wrapper">
<p class="text-center">You are currently logged in as @currentEmployee.FirstName @currentEmployee.LastName.</p>
<input type="hidden" id="EmployeeID" name="EmployeeID" value="@currentEmployee.EmployeeID"/>
<div class="row">
<div class="col-md-12">
<input type="submit" value="@btnValue" class="btn btn-primary @btnClass" />
</div>
</div>
</div>
}
}
Here is my Controller:
// POST: TimeEntries/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "TimeEntryID,EmployeeID,TimeStart,TimeEnd,IsClosed")] TimeEntry timeEntry) {
var currentUserId = User.Identity.GetUserId();
var currentUser = db.AspNetUsers.FirstOrDefault(c => c.Id == currentUserId);
var currentEmployee = db.Employees.FirstOrDefault(c => c.EmployeeID == currentUser.EmployeeID);
ViewBag.CurrentEmployee = currentEmployee;
var existingTimeEntry = db.TimeEntries.FirstOrDefault(te => te.EmployeeID == currentEmployee.EmployeeID && te.IsClosed == false);
ViewBag.ExistingTimeEntry = existingTimeEntry;
var timeEntryID = -1;
if (existingTimeEntry != null)
{
timeEntryID = existingTimeEntry.TimeEntryID;
}
ViewBag.EmployeeID = new SelectList(db.Employees, "EmployeeID", "FirstName");
if (ModelState.IsValid)
{
if (timeEntryID <= 0)
{
// Grab the current employee and set clocked in to true.
var employee = db.Employees.Find(timeEntry.EmployeeID);
employee.IsClockedIn = true;
// Create the time entry.
timeEntry.TimeStart = DateTime.Now;
timeEntry.IsClosed = false;
db.TimeEntries.Add(timeEntry);
ViewBag.CurrentTimeEntry = timeEntry;
db.SaveChanges();
return Json(timeEntry, JsonRequestBehavior.AllowGet);
}
else {
var updatedTimeEntry = db.TimeEntries.Find(timeEntryID);
var employee = db.Employees.Find(timeEntry.EmployeeID);
employee.IsClockedIn = false;
updatedTimeEntry.TimeEnd = DateTime.Now;
updatedTimeEntry.IsClosed = true;
db.SaveChanges();
return Json(updatedTimeEntry, JsonRequestBehavior.AllowGet);
}
}
ViewBag.EmployeeID = new SelectList(db.Employees, "EmployeeID", "FirstName", timeEntry.EmployeeID);
return View(timeEntry);
}
And here is my jQuery:
$(function () {
$("#clock-in-form").on("submit", function (e) {
e.preventDefault();
var submitButton = $("#clock-in-form input[type='submit']");
var dt = new Date();
var formData = $(this).serialize();
$.ajax({
type: "POST",
url: "/TimeEntries/Create",
data: JSON.stringify(formData),
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function(data) {
if (submitButton.hasClass("clock-in-btn")) {
submitButton.removeClass("clock-in-btn");
submitButton.addClass("clock-out-btn");
submitButton.attr("value", "Clock Out");
console.log(data);
$(".clock-in-alerts").append('<div class="alert alert-success text-center">You have successfully logged in at ' + data.TimeStart + '.</div>');
} else if (submitButton.hasClass("clock-out-btn")) {
submitButton.removeClass("clock-out-btn");
submitButton.addClass("clock-in-btn");
submitButton.attr("value", "Clock In");
}
},
error: function (xhr, status, error) {
console.log(xhr);
console.log(status);
console.log(error);
}
});
});
});
When I try to submit the form I get an Internal Server Error (500) and in the response text it says "The required anti-forgery form field “__RequestVerificationToken” is not present."
Upvotes: 0
Views: 1582
Reputation: 993
You need to add the antiforgery token to the header of your request. You can either do that for each request, or you can use ajaxSetup to add it to every request.
Try something like this:
jQuery(document).ready(function ($) {
$.ajaxSetup({
type: "POST",
headers: { "__RequestVerificationToken": $('[name=__RequestVerificationToken]').val() }
});
});
Check out a related question for more information: jQuery Ajax calls and the Html.AntiForgeryToken()
Upvotes: 1