I have a view that is NOT a form. I am doing an Ajax POST with jQuery to the server without having any form at all. It displays a blog and also it accepts a blog comment. I want to take that blog comment and save it to the database.
I'm getting: The required anti-forgery form field"__RequestVerificationToken" is not present in asp.net mvc
I modified the code to reflect the suggestions from a prior solution.
I have a @Html.AntiForgeryToken() right before the text field (the blog comment) that I want to use to save to the database.
I have the [ValidateAntiForgeryToken] attribute before the controller aciton method.
I pass append the token to the data to be sent to the method: data: AddAntiForgeryToken({ blogComment, userProfileProcessType }),
But it still does not work.
Here is the view:
<h2 class="page-header"><span class="blogtitle">@Session["BlogTitle"]</span></h2>
@{
Layout = "~/Views/Shared/_LayoutUser.cshtml";
}
@if (ViewBag.errormessage != null)
{
<p class="alert alert-danger" id="errorMessage">@ViewBag.errormessage</p>
}
<br />
<div>
<a href="@Url.Action("LoadDropdownBlogCategorysInBlogsPublished", "BlogPublished")">Return To Select a Blog</a>
</div>
<br />
@if (Model != null)
{
<div class="panel panel-default toppanel">
<div class="panel-body">
<div class="row">
<div class="col-md-2">
@Html.LabelFor(model => model.BlogPublishedByBlogId.CreatedDateTime)
@Html.TextBoxFor(model => model.BlogPublishedByBlogId.CreatedDateTime, new { @class = "form-control", @disabled = "disabled" })
</div>
<div class="col-md-2">
@Html.LabelFor(model => model.BlogPublishedByBlogId.ModifiedDateTime)
@Html.TextBoxFor(model => model.BlogPublishedByBlogId.ModifiedDateTime, new { @class = "form-control", @disabled = "disabled" })
</div>
</div>
<br />
<div class="row">
<div>
@Html.DisplayFor(model => model.BlogPublishedByBlogId.BlogContent, new { @class = "form-control blogContent", @disabled = "disabled" })
</div>
</div>
<br />
<br />
<div class="panel-footer">
<button type="button" class="btn btn-primary Comment" data-id="@Model.BlogPublishedByBlogId.BlogId" value="Comment">
<span class="glyphicon glyphicon-comment" aria-hidden="true"></span> Get Comment(s)
</button>
</div>
<div id="@string.Format("{0}_{1}","commentsBlock", @Model.BlogPublishedByBlogId.BlogId)" style="border: 1px solid #f1eaea; background-color: #eaf2ff;">
<div class="AddCommentArea" style="margin-left: 30%; margin-bottom: 5px; margin-top: 8px;">
@Html.AntiForgeryToken()
<input type="text" id="@string.Format("{0}_{1}", "comment", @Model.BlogPublishedByBlogId.BlogId)" class="form-control" placeholder="Add a comment..." style="display: inline;" />
<button type="button" class="btn btn-primary addComment" data-id="@Model.BlogPublishedByBlogId.BlogId"><span class="glyphicon glyphicon-comment" aria-hidden="true"></span></button>
</div>
</div>
</div>
</div>
}
@Scripts.Render("~/bundles/jqueryval")
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@Styles.Render("~/Content/css")
@section Scripts
{
<script type="text/javascript">
$(document).ready(function () {
$('.Comment').on('click', function () {
var blogId = $(this).attr("data-id");
var allCommentsArea = $('<div>').addClass('allComments_' + blogId);
$.ajax({
type: 'GET',
url: '@Url.Action("GetBlogComments", "BlogPublished")',
data: { blogId: blogId },
success: function (response) {
if ($('div').hasClass('allComments_' + blogId + ''))
{
$('div[class=allComments_' + blogId + ']').remove();
}
// Dynamically building the HTML to hold the comments (the list) returned.
// The area for the BlogPublished/_Comments.cshtml to be placed.
allCommentsArea.html(response);
allCommentsArea.prependTo('#commentsBlock_' + blogId);
},
error: function (xhr, ajaxOptions, thrownError) {
alert("Critical Error: something is wrong in the call to GetBlogComments! Status: " + xhr.status + ". Error: " + thrownError.toString() + ". Response Text: " + xhr.responseText);
}
})
});
// For when clicking the 'addComment' button.
$('.addComment').on('click', function () {
var blogId = $(this).attr('data-id');
var blogCommentContent = $('#comment_' + blogId).val();
var dateTimeNow = new Date();
var userProfileProcessType = "I";
// An object - the BlogComment model to be passed to the controller method.
var blogComment = {
BlogId: blogId,
BlogCommentContent: blogCommentContent,
DateTimeOfBlogComment: dateTimeNow.toLocaleString()
};
$.ajax({
type: 'POST',
url: '@Url.Action("ProcessSaveBlogComment", "BlogPublished")',
data: AddAntiForgeryToken({ blogComment, userProfileProcessType }),
success: function (response) {
$('div[class=allComments_' + blogId + ']').remove();
// Dynamically building the HTML to hold the comments (the list) returned which now includes the added comment.
var allCommentsArea = $('<div>').addClass('allComments_' + blogId);
allCommentsArea.html(response);
allCommentsArea.prependTo('#commentsBlock_' + blogId);
$("#comment_" + blogId).val('')
},
error: function (xhr, ajaxOptions, thrownError) {
alert("Critical Error: something is wrong in the call to ProcessSaveBlogComment! Status: " + xhr.status + ". Error: " + thrownError.toString() + ". Response Text: " + xhr.responseText);
}
});
});
jQuery(".timeago").timeago();
});
AddAntiForgeryToken = function (data) {
data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val();
return data;
};
</script>
}
Here is the controller:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ProcessSaveBlogComment(BlogComment blogComment, string userProfileProcessType)
{
if (ModelState.IsValid)
{
blogComment.UserId = Convert.ToInt32(Session["UserId"]);
BLL_BlogPublished bll_BlogPublished = new BLL_BlogPublished();
ProcessSaveBlogCommentResults processSaveBlogCommentResults = new ProcessSaveBlogCommentResults();
try
{
processSaveBlogCommentResults = await bll_BlogPublished.ProcessSaveBlogComment(blogComment, Session["UserName"].ToString(), userProfileProcessType);
if (processSaveBlogCommentResults.ApiErrorMessage == null)
{
if (processSaveBlogCommentResults.Status == 2)
{
ViewBag.errormessage = "Process Violation: You are not the 'blog comment' creator so you cannot update the blog comment.";
}
else if (processSaveBlogCommentResults.Status == 3)
{
ViewBag.errormessage = "Process Violation: Not the correct 'blog id' so cannot update the blog comment.";
}
}
else
{
ViewBag.errormessage = processSaveBlogCommentResults.ApiErrorMessage;
}
}
catch (Exception ex1)
{
exceptionMessage = "Server error on saving the blog comment. Please contact the administrator.";
try
{
ClientErrorResult clientErrorResult = new ClientErrorResult();
clientErrorResult = await ProcessClientError(Session["UserName"].ToString(), ex1.Message, "Server error on saving the blog comment. User name: " + Session["UserName"] + ". Post method: ProcessSaveBlogComment.");
if (clientErrorResult.ApiErrorMessage == null)
{
ViewBag.errormessage = exceptionMessage;
}
else
{
ViewBag.errormessage = clientErrorResult.ApiErrorMessage;
}
}
catch (Exception ex2)
{
ViewBag.errormessage = "Failure in ProcessClientError. Exception error: " + ex2.Message + ". Original error: " + exceptionMessage;
}
}
}
return RedirectToAction("GetBlogComments", "BlogPublished", new {blogId = blogComment.BlogId });
}
Before leaving the AddAntiForgeryToken function - the console log.
The network tab - cookies.
Part 1 of the Network tab - header (has the request verification token in the cookie).
Part 2 of the Network tab - header (has the my data to send to the controller).
Error:
8/13/2020 4:49:56 PM
Controller Name :- BlogPublished Action Method Name :- ProcessSaveBlogComment
System.Web.Mvc.ExceptionContext Message --- {0}The required anti-forgery form field "__RequestVerificationToken" is not present. .Net Error --- {0}Check MVC Ajax Code For Error Source --- {0}System.Web.WebPages StackTrace --- {0} at System.Web.Helpers.AntiXsrf.TokenValidator.ValidateTokens(HttpContextBase httpContext, IIdentity identity, AntiForgeryToken sessionToken, AntiForgeryToken fieldToken) at System.Web.Helpers.AntiXsrf.AntiForgeryWorker.Validate(HttpContextBase httpContext) at System.Web.Helpers.AntiForgery.Validate() at System.Web.Mvc.ValidateAntiForgeryTokenAttribute.OnAuthorization(AuthorizationContext filterContext) at System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor) at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass3_1.b__0(AsyncCallback asyncCallback, Object asyncState) TargetSite --- {0}Void ValidateTokens(System.Web.HttpContextBase, System.Security.Principal.IIdentity, System.Web.Helpers.AntiXsrf.AntiForgeryToken, System.Web.Helpers.AntiXsrf.AntiForgeryToken)