Asp.net MVC, 4.0 - Ajax, field value is overriden after update - ajax

I am playing around with some ajax, and have experienced a very odd and to me illogical bug.
I am displaying a list of events, wrapped in a form, in a table. Each event has a unique ID (EventID). This is submitted to the action when a button is pressed.
A div surrounding the table is now updated with the partialview that the action has returned.
The problem
When the view is reloaded, all the HiddenFields that contains the field EventID, now cointains the same EventID as. the one that was submitted to the action
I have tried placing a breakpoint in the view, to see what value is put in the HiddenField. Here is see that the correct id is actually set to the field. but when the page updates, all the hiddenfields contains the same eventid as the one originally submitted to the action.
The partialview: _Events
#model SeedSimple.Models.ViewModelTest
<table class="table table-striped table-bordered table-condensed">
#foreach (var item in Model.events)
{
#using (Ajax.BeginForm("AddAttendantToEvent", "MadklubEvents", new AjaxOptions()
{
HttpMethod = "post",
UpdateTargetId = "tableevents"
}))
{
#Html.Hidden("EventID", item.MadklubEventID);
<input type="submit" value="Join!" id="join" class="btn" />
}
#using (Ajax.BeginForm("RemoveAttendantFromEvent", "MadklubEvents", new AjaxOptions()
{
HttpMethod = "post",
UpdateTargetId = "tableevents"
}))
{
#Html.Hidden("EventID", item.MadklubEventID);
<input type="submit" value="Leave" class="btn" />
}
}
</table>
AddAttendantToEvent Action:
[HttpPost]
[Authorize]
public ActionResult AddAttendantToEvent(int EventID)
{
if (ModelState.IsValid)
{
var uow = new RsvpUnitofWork();
var currentUser = WebSecurity.CurrentUserName;
var Event = uow.EventRepo.Find(EventID);
var user = uow.UserRepo.All.SingleOrDefault(u => u.Profile.UserName.Equals(currentUser));
user.Events.Add(Event);
Event.Attendants.Add(user);
uow.Save();
ViewModelTest viewmodel = new ViewModelTest();
viewmodel.events = madklubeventRepository.AllIncluding(madklubevent => madklubevent.Attendants).Take(10);
viewmodel.users = kitchenuserRepository.All;
return PartialView("_Events", viewmodel);
}
else
{
return View();
}
}
How all the input fields look after having submitted EventID 4 to the action
<input id="EventID" name="EventID" type="hidden" value="4">
I am suspecting, this is due to some side-effects from the ajax call, that i am unknown to.
Any enlightentment on the subject would be much appreciated :)

Related

MVC 4 Razor using Ajax forms to update a foreach loop

Where to start...I can find similar things on the Internet as to how, but they never seem to work with my specific way of wanting to do something. I have tried with and without partial views with very little success.
Quick rundown: I have a strongly-typed View with an Ajax form. underneath the form, I have a foreach loop that repeats a code block. I need to be able to update the code block from the forms choices (filters).
Here's my View, 'FindATeacher.cshtml', as it currently stands (after trying many different ideas):
#model Teachers.Models.OmniModel
#{
ViewBag.Title = "FindATeacher";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Find a Teacher</h2>
#using (Ajax.BeginForm("FilterTeachers", "Home", new AjaxOptions { HttpMethod = "Post", OnSuccess = "onSuccess" }))
{
<div id="ContentFilter">
<div class="filterLabels">
<p>Search by Name</p>
<p>Filter By Instrument</p>
<p>Filter By City</p>
</div>
<div class="filterObjects">
<p>
<input type="text" id="nameTXT" />
<button type="submit" id="findButton">find</button>
</p>
<p>#Html.DropDownList("InstrumentID", (SelectList)Model.Instruments, "-- Select an Instrument --", new { id = "instrumentDD" })</p>
<p>#Html.DropDownList("CityID", (SelectList)Model.Cities, "-- Select a City --", new { id = "cityDD" })</p>
</div>
</div>
}
<hr />
#foreach (var r in Model.Teachers)
{
<div id="ContentResults">
<div id="avatar">
<img src="i" />
</div>
<div id="demographics">
<h6>#r.Teacher</h6>
<strong>#r.StudioName</strong>
<p>#r.URL</p>
<p>#r.StreetAddress</p>
<p>#r.City, #r.AddressStateID #r.Zip</p>
<p>#r.Phone</p>
<p>#r.EmailAddress</p>
</div>
<div id="studioDetails">
<p><strong>Instrument(s) Taught</strong></p>
<p>
#{
var instrumentString = r.Instruments.Aggregate("", (a, b) => a + b.Instrument + ", ");
if (instrumentString.Length != 0)
{
instrumentString = instrumentString.Remove(instrumentString.LastIndexOf(","));
}
}
#instrumentString
</p>
<br />
#if (r.Information != "" && r.Information != null)
{
<p><strong>Information</strong></p>
<p>#r.Information</p>
}
</div>
</div>
}
Now here's my Controller. I get the results back correctly in the Controller, just not updating the code block:
public ActionResult FindATeacher()
{
Model.Instruments = new SelectList(TeacherService.GetInstrumentList(0),"InstrumentID","Instrument");
Model.Cities = new SelectList(TeacherService.GetCityList(),"CityID","City");
Model.Teachers = TeacherService.GetTeacherList("", 0);
return View(Model);
}
[HttpPost]
public JsonResult FilterTeachers(String teacherName, String instrumentID, String cityID)
{
Model.Teachers = TeacherService.GetTeacherList("John", 0, 0);
return Json(Model.Teachers);
}
Thanks.
#VishalVaishya presents the right idea, but there's a simpler way, which doesn't involve custom javascript code: AjaxOptions has an UpdateTargetId property that the AJAX toolkit will interpret to mean you want the given target to be updated with the results sent back from the controller.
FindATeacher.cshtml:
#using (Ajax.BeginForm("FilterTeachers", "Home", new AjaxOptions {
HttpMethod = "Post", UpdateTargetId = "TeacherList" }))
{
...
}
<hr />
<div id="TeacherList">
#Partial("TeacherList", Model.Teachers)
</div>
TeacherList.cshtml
#model IEnumerable<Teacher>
#foreach(var teacher in Model)
{
...
}
Controller action:
[HttpPost]
public ActionResult FilterTeachers(String teacherName, String instrumentID, String cityID)
{
Model.Teachers = TeacherService.GetTeacherList(teacherName, instrumentID, cityID);
return PartialView("TeacherList", Model.Teachers);
}
You can try following method:
Separate your foreach loop into another partial view.
And load your partial view on filter / click event and pass filtered parameters to your controller-action.
JS change event code will be something like this:
var teacherName = ''; //get your selected teachername
var instrumentID = ''; //get your selected instrumentid
var cityID = ''; //get your selected city id
var url = '#Url.Action("FilterTeachers", "ControllerName", new { teacherName = "teacher-Name", instrumentID="instrument-ID", cityID="city-ID" })';
url = url.replace("teacher-Name", teacherName).replace("instrument-ID", instrumentID).replace("city-ID", cityID);
$('#result').load(url);

How to use ajax link instead of submit button for form?

I have Ajax Form in my view:
#using (Ajax.BeginForm("SearchHuman", "Search", new AjaxOptions(){
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "result" }))
{
<div class="editor-field">
#DescriptionStrings.Lastname:
#Html.TextBox("LastName")
</div>
<div class="editor-field">
#DescriptionStrings.Firstname:
#Html.TextBox("Name")
</div>
//submit button
<input type="submit" value='Start Searching' />
//submit link
#Ajax.ActionLink("search", "OtherSearch", new{lastName ="",...}, new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "tab"
})
}
I want to have submit button and the link for 2 different searches (in different databases) using only one form. But how to pass route values from the textboxes of the form into Ajax.ActionLink?
Thanks in advance!
But how to pass route values from the textboxes of the form into Ajax.ActionLink?
You can't. You should use a submit button if you want to send the values to the server. You could have 2 submit buttons in the same form which both submit to the same controller action. Then inside this action you can test which button was clicked and based on its value perform one or the other search.
Example:
<button type="submit" name="btn" value="search1">Start Searching</button>
<button type="submit" name="btn" value="search2">Some other search</button>
and then inside your controller action:
[HttpPost]
public ActionResult SomeAction(string btn, MyViewModel model)
{
if (btn == "search1")
{
// the first search button was clicked
}
else if (btn == "search2")
{
// the second search button was clicked
}
...
}
The solution we opted for was to implement a custom ActionMethodSelectorAttribute which allowed us to differentiate which button was pressed based on its name property. We then decorated many methods with the ActionName decorator giving them all the same action name (the one specified in the BeginFrom helper), and then we used our custom ActionMethodSelector decorator to differentiate which method is to be called based on the name of the button clicked. The net result is that each submit button leads to a separate method being called.
Some code to illustrate:
In controller:
[ActionName("RequestSubmit")]
[MyctionSelector(name = "Btn_First")]
public ActionResult FirstMethod(MyModel modelToAdd)
{
//Do whatever FirstMethod is supposed to do here
}
[ActionName("RequestSubmit")]
[MyctionSelector(name = "Btn_Second")]
public ActionResult SecondMethod(MyModel modelToAdd)
{
//Do whatever SecondMethod is supposed to do here
}
In view:
#using (Ajax.BeginForm("RequestSubmit",.....
<input type="submit" id="Btn_First" name="Btn_First" value="First"/>
<input type="submit" id="Btn_Second" name="Btn_Second" value="Second"/>
As for the custom attribute:
public string name { get; set; }
public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
{
var btnName = controllerContext.Controller.ValueProvider.GetValue(name);
return btnName != null;
}

Result not showing with unobtrusive ajax in mvc 3

I'm trying to implement a little ajax using unobtrusive ajax of mvc 3. Here is the code snippet:
Controller:
[HttpGet]
public ActionResult ViewEmployee()
{
return View();
}
[HttpPost]
public ActionResult ViewEmployee(EMPLOYEE model)
{
var obj = new EmployeeService();
var result=obj.FindEmployee(model);
return View("ViewEmployee", result);
}
View:
#{AjaxOptions AjaxOpts = new AjaxOptions { UpdateTargetId = "ajax", HttpMethod = "Post" };}
#using (Ajax.BeginForm("ViewEmployee", "Home", AjaxOpts))
{
#Html.LabelFor(x => x.EmployeeID)
#Html.TextBoxFor(x => x.EmployeeID)
<input type="submit" name="Find Name" value="Find Name" />
}
<div id="ajax">
#{
if (Model != null)
{
foreach (var x in Model.EmployeeName)
{
#x
}
}
else
{
#Html.Label("No Employee is selected!")
}
}
</div>
I debugged the code, its sending the employee id to the ViewEmployee method, finding the name but not being able to display the name back into the view.
I've activated the unobtrusive ajax property in web.config & imported the scripts into the view.
Whats going wrong with this? Please help.
This is simple but effective article, ask me if you have any more question! I resolved the problem! By the way, whats wrong with stackoverflow, i'm not getting no response literally!
http://www.c-sharpcorner.com/UploadFile/specialhost/using-unobtrusive-ajax-forms-in-Asp-Net-mvc3/

The error of can not find View in Ajax form

I ask a similar question here
So I add Some OnComplete Functions and Id to Ajax Forms, And there is:
This is My View:
#foreach(var item in Model) {
<tr id="TR#(item.Id)">
#{Html.RenderPartial("_PhoneRow", item);}
</tr>
}
_PhoneRow:
#model PhoneModel
#using(Ajax.BeginForm("EditPhone", new { id = Model.Id }, new AjaxOptions {
UpdateTargetId = "TR" + Model.Id,
OnComplete = "OnCompleteEditPhone"
}, new { id = "EditAjaxForm" + Model.Id})) {
<td>#Html.DisplayFor(modelItem => Model.PhoneNumber)</td>
<td>#Html.DisplayFor(modelItem => Model.PhoneKind)</td>
<td><input type="submit" value="Edit" class="CallEditPhone" id="edit#(Model.Id)" /></td>
}
Controller:
public ActionResult EditPhone(long Id) {
//Get model by id
return PartialView("_EditPhoneRow", model);
}
public ActionResult SavePhone(PhoneModel model) {
//Save Phone, and Get Updatet model
return PartialView("_PhoneRow", model);
}
_EditPhoneRow
#model PhoneModel
#using(Ajax.BeginForm("SavePhone", new { id = Model.Id }, new AjaxOptions {
UpdateTargetId = "TR" + Model.Id,
OnComplete = "OnCompleteSavePhone"
})) {
<td>#Html.EditorFor(modelItem => Model.PhoneNumber)</td>
<td>#Html.EditorFor(modelItem => Model.PhoneKind)</td>
<td><input type="submit" value="Save" class="SaveEditPhone" id="save#(Model.Id)" /></td>
}
And Oncomplete Scripts:
function OnCompleteEditPhone() {
$('input.SaveEditPhone').click(function () {
var id = $(this).attr("id").substring(4);
$('form#SaveAjaxForm' + id).trigger('submit');
});
}
function OnCompleteSavePhone() {
$('input.CallEditPhone').click(function () {
var id = $(this).attr("id").substring(4);
$('form#EditAjaxForm' + id).trigger('submit');
});
}
So Click Edit Worked perfect, Then Click Save Worked good also, But in second time when i click the Edit Button I have an Error in Post Action I copy the Firebug console here:
http://Mysite/members/editphone/7652 200 OK 582ms
http://Mysite/members/savephone/7652 200 OK 73ms
http://Mysite/members/editphone/7652 500 internal server error 136ms
<title>The view 'EditPhone' or its master was not found or no view engine supports the searched locations. The following locations were searched: ...
So where is the problem? If I remove OnCompleteSavePhone The Edit button for second time not worked, and with this function I have an error that not make any sense, How Can I fix it? I actually load partial views by Ajax, And need the buttons of this views worked correctly, at first every thing is fine but after Ajax result They don't, I think to add some Oncomplete functions, but there is an error also.
Your previous question is answered now. You had broken markup. As a consequence of this you no longer need to care about any OnComplete events and doing some auto triggers, form submissions and stuff. This will be handled by the Ajax.BeginForm infrastructure automatically for you.

mvc3 how do I clear the submitted form values

I am new to asp .net mvc3. I am trying to create a failrly simple blog comments section.
I have a CommentsViewModel
public class CommentsViewModel
{
public CommentModel NewComment { get; set; }
public IList<CommentModel> CommentsList { get; set; }
}
The corresponding view is like
<div id="CommentsArea">
#Html.Partial("CommentsList", Model.CommentsList)
</div>
#using (Ajax.BeginForm("Create",
"Comment",
new { id = Model.NewComment.detailsId, comment = Model.NewComment },
new AjaxOptions { UpdateTargetId = "CommentsArea" ,
HttpMethod = "Post",
InsertionMode = InsertionMode.Replace}))
{
<div class="display-label">Add Comment</div>
<div class="display-field">
#Html.EditorFor(model => Model.NewComment.Body)
</div>
<input type="submit" value="Post" />
}
Now when user enters Post button I want the "CommentsArea" to be updated with the new comments list and also the form values to be cleared with empty text.
Here is the Post method:
[HttpPost]
public ActionResult Create(int id, CommentModel newcomment)
{
var newsItem = m_db.NewsList.Single(news => news.Id == id);
if (!string.IsNullOrWhiteSpace(newcomment.Body))
{
newcomment.detailsId = id;
newsItem.Comments.Add(newcomment);
m_db.SaveChanges();
}
return PartialView("CommentsList", newsItem.Comments);
}
Now when user clicks Post button the list gets updated properly,
but the form values are not cleared. i.e. if I posted a comment "New Comments", the comments list gets updated with "New Comments", but that text remains inside the edit box of the form.
How do I clear that text?
just call a js function on success of form submit.
#using (Ajax.BeginForm("Create",
"Comment",
new { id = Model.NewComment.detailsId, comment = Model.NewComment },
new AjaxOptions { OnSuccess="ClearInput", HttpMethod = "Post",}))
on js function render create view again
function ClearInput(){
//call action for render create view
$.ajax({})
}

Resources