I have a comments section. In the view there is only a comments editor box.
@using (Html.BeginForm(new { courseID = @ViewBag.courseID, userName = @User.Identity.Name }))
{
@Html.ValidationSummary(true)
<div class="NewComment">
<div class="editor-field">
@Html.TextAreaFor(model => model.CommentText, new { maxLength = 500})
@Html.ValidationMessageFor(model => model.CommentText)
</div>
<input type="submit" class="PostComment" value="Post Comment" />
<div id="Counter" class="CommentCounter"/>
</div>
}
The model has the course the comment is linked too, date, comment text, and user. The other values get filled in the create post method.
[HttpPost]
public ActionResult AddComment(CourseComment coursecomment, int courseID, String userName)
{
userName = userName.Split('\\')[1];
coursecomment.CommentDate = System.DateTime.Now;
coursecomment.CourseID = courseID;
coursecomment.UserName = db.Users.FirstOrDefault(u => u.UserName == userName).UserID;
if (ModelState.IsValid)
{
db.CourseComments.AddObject(coursecomment);
db.SaveChanges();
}
return RedirectToAction("Details", "Course", new { courseID = courseID });
}
The problem occurs here. The model is trying to use the userName parameter for the value for courseComment.UserName before I actually do the work and set it. After it gets set the ModelState doesn't change.
Example, domain\abc123 gets passed into the post method and also set in the ModelState for UserName. I do some work, change the userName to abc123 and find the linked ID, lets say ID = 1, to that user with said name, then plug that into the courseComment.UserName ModelState still leaves the domain\abc123 in there and the model stays invalid.
Now, this was working original, then I changed the underlying database around, mainly just column names and some relations.
My solution for this.
Move receiving the username from the post method
[HttpPost]
public ActionResult AddComment(CourseComment coursecomment, int courseID)
{
coursecomment.CommentDate = System.DateTime.Now;
coursecomment.CourseID = courseID;
coursecomment.UserName = db.Users.FirstOrDefault(u => u.UserName == userName).UserID; //Moved
if (ModelState.IsValid)
{
db.CourseComments.AddObject(coursecomment);
db.SaveChanges();
}
return RedirectToAction("Details", "Course", new { courseID = courseID });
}
to a get method.
[HttpGet]
public JsonResult GetUserName(string userName)
{
var ret = db.Users.FirstOrDefault(u => u.UserName == userName).UserID;
return Json(ret, JsonRequestBehavior.AllowGet);
}
Then changed the view to be like
@Html.HiddenFor(model => model.UserName)
....
<script type="text/javascript">
$(function () {
var userName = '@User.Identity.Name.Split('\\')[1]';
$.ajax({
url: '@Url.Action("GetUserName", "CourseComment")',
data: { userName: userName },
type: 'get'
}).done(function (data) {
$('#UserName').val(data);
});
});