MVC3 Razor script reloading issue even with unobtrusive - asp.net-mvc-3

Even using the unobtrusive ajax library, the scripts loaded into this page from the _Login.cshtml file are loaded when the form is submitted and I do not know how to prevent this. An even stranger effect is when an onclick event is applied to any element, when the form is submitted the script gets executed by the number of times the element was clicked.
Edit
On further testing, I realized that the unobtrusive ajax library basically re-loads the whole page inside the UpdateTargetId element, which is VERY counterproductive. This means if I submit the page 4 times, the page is loaded subsequently within each UpdateTargetId element, on each page within the page. What am I doing wrong? Is that what it's supposed to do?
#using MinervaMvc.App_Data
#model MinervaMvc.Models.LogOnModel
#{
ViewBag.Title = "Home Page";
Layout = "~/Views/Shared/_Login.cshtml";
}
<div id="loginContainer">
<h2>
Login</h2>
<div id="loginForm">
#{Html.EnableClientValidation();}
#using (Ajax.BeginForm(new AjaxOptions { HttpMethod = "POST" }))
{
<table style="margin: 0px auto;">
<tr>
<td>
#Html.LabelFor(m => m.ServerName, new { #class = "label" })
</td>
<td>
#Html.TextBoxFor(m => m.ServerName, new { #class = "text" })
</td>
</tr>
<tr>
<td align='right'>
#Html.LabelFor(m => m.UserName, new { #class = "label" })
</td>
<td>
#Html.TextBoxFor(m => m.UserName, new { #class = "text" })
</td>
</tr>
<tr>
<td align='right'>
#Html.LabelFor(m => m.Password, new { #class = "label" })
</td>
<td>
#Html.PasswordFor(m => m.Password, new { #class = "text" })
</td>
</tr>
<tr>
<td align="right" colspan="2">
<div id='errorShade' class='shade'>
<div id='errorBox'>Password or Username is incorrect. Please try again.</div>
</div>
</td>
</tr>
<tr>
<td align="right" colspan="2">
<div id='loginShade' class='shade'>
<input type='submit' class='button' id='btn' value='Login' /></div>
</td>
</tr>
</table>
<div id='ajaxUpdate' style='position: absolute; visibility: hidden;'>
#{if (ViewBag.Failed != null && ViewBag.Failed)
{
<script type="text/javascript">
pulseState.stopPluse = true;
hideShowLogin(true, 'errorShade', 20);
hideShowLogin(false, 'loginShade', 33);
</script>
}}
</div>
}
</div>
</div>
<br />
<div id="copywrite">
#{ Html.RenderPartial("Copyright"); }
</div>

First things first you don't need the following line:
#{Html.EnableClientValidation();}
Simply enable client validation in your web.config (should be by default):
<appSettings>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
<add key="ClientValidationEnabled" value="true"/>
</appSettings>
Then make sure that you have included the following script into your page:
jquery-1.5.1.js
jquery.validate.js
jquery.validate.unobtrusive.js
jquery.unobtrusive-ajax.js (this is for all the Ajax.* helpers to work, it has nothing to do with validation)
As far as the whole page reloading is concerned, when you specify an UpdateTargetId element in the AJAX options, this element is updated with the results of the AJAX request returned by the server (often a partial).

Related

.NET MVC Ajax.ActionLink not returning partial view

I have been researching and trying multiple failed attempts FOR DAYS to get my partial view to display within my main view using Ajax.actionlink. When using the developer tools and viewing the Network tab, I do see the request. When clicking on Preview, I can see the correct data within the partial view. No jQuery errors.
View
#model IEnumerable<NS.Models.FeeAuth>
#using (Html.BeginForm())
{
<p>
<span class="glyphicon glyphicon-search"></span> Find by Last Name: #Html.TextBox("SearchString")
<input type="submit" value="Search" />
</p>
}
<div class="table-responsive">
<table class="table table-condensed" style="border-collapse:collapse;">
<tr>
<th>
#Html.LabelFor(m => m.First().ID)
</th>
<th>
#Html.ActionLink("Request ID", "ApprovalIndex", new { sortOrder = ViewBag.RequestIDSortParam })
</th>
<th>
#Html.Label("emplid", "Student Emplid")
</th>
</tr>
#{int i = 0;}
#foreach (var item in Model)
{
<tr data-toggle="collapse" data-parent="#collapse1_#i" data-target="#collapse1_#i" class="accordion-toggle">
<td>
#Ajax.ActionLink(Html.Encode(item.ID),
"SelectedSTRMS",
"FeeAuth",
new { id = item.ID, requestId = item.requestID },
new AjaxOptions
{
HttpMethod = "GET",
UpdateTargetId = "SelectedSTRMList" + i,
InsertionMode = InsertionMode.Replace
})
</td>
<td>
#Html.DisplayFor(modelItem => item.requestID)
</td>
<td>
#Html.DisplayFor(modelItem => item.emplid)
</td>
</tr>
<tr>
<td colspan="6" class="hiddenRow">
<div class="accordion-body collapse" id="collapse1_#i">
<div id="SelectedSTRMList_#i">
</div>
</div>
</td>
</tr>
i++;
}
</table>
</div>
Partial View
<table>
<tr>
<td>
<ul>
#foreach (var s in (List<string>)ViewBag.SemesterInfo)
{
<li style="padding-bottom:20px;">#s</li>
}
</ul>
</td>
</tr>
</table>
Jquery in _Layout.cshtml
<script src="~/Scripts/jquery-2.1.3.js" type="text/javascript"></script>
<script src="~/Scripts/jquery-migrate-1.2.1.min.js" type="text/javascript"></script>
<script src="~/Scripts/jquery.validate.js" type="text/javascript"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js" type="text/javascript"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js" type="text/javascript"></script>
Controller
[HttpGet]
public PartialViewResult SelectedSTRMS(int id, int requestId)
{
FeeAuthWithCommentsViewModel feeauth = new FeeAuthWithCommentsViewModel();
feeauth.FeeAuth = db.FeeAuths.Find(id);
int feeauthID = id;
List<string> GetSTRM = new List<string>();
GetSTRM = db.vw_GetSTRMs.Where(v => v.FeeAuthID == feeauthID).Select(v => v.DESCR).ToList();
if (GetSTRM.Count > 0)
{
ViewBag.SemesterInfo = GetSTRM.ToList();
}
else
{
ViewBag.SemesterInfo = new List<string> { "No STRM Selected" };
}
return PartialView("_SelectedSTRMS");
}
Your update target is:
UpdateTargetId = "SelectedSTRMList" + i,
But your div id is:
<div id="SelectedSTRMList_#i">
In other words, you're either missing an _ in the update target string or you need to remove the _ in your div id.

Post multiple data from an loaded form ajax mvc 4

I have a form like this
<table>
<thead>
<tr>
<th>Tên học sinh </th>
<th>Giáo lý viên </th>
<th>Năm Học</th>
<th>Điểm TB Học Kỳ 1 </th>
<th>Điểm TB Học Kỳ 2 </th>
<th>Điểm Tổng Kết Năm Học </th>
<th>Lớp </th>
</tr>
</thead>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset class="form-horizontal">
<tbody id="addDetails">
<tr>
<td>
#Html.DropDownList("HocSinhId", String.Empty)
#Html.ValidationMessageFor(model => model.HocSinhId, null, new { #class = "help-inline" })
</td>
<td>
#Html.DropDownList("GiaoLyVienId", String.Empty)
#Html.ValidationMessageFor(model => model.GiaoLyVienId, null, new { #class = "help-inline" })
</td>
<td>
#Html.TextBoxFor(model => model.NamHoc)
#Html.ValidationMessageFor(model => model.NamHoc, null, new { #class = "help-inline" })
</td>
<td>
#Html.EditorFor(model => model.DiemTBHK1)
#Html.ValidationMessageFor(model => model.DiemTBHK1, null, new { #class = "help-inline" })
</td>
<td>
#Html.EditorFor(model => model.DiemTBHK2)
#Html.ValidationMessageFor(model => model.DiemTBHK2, null, new { #class = "help-inline" })
</td>
<td>
#Html.EditorFor(model => model.DiemTongKetNamHoc)
#Html.ValidationMessageFor(model => model.DiemTongKetNamHoc, null, new { #class = "help-inline" })
</td>
<td>
#Html.DropDownList("LopId", String.Empty)
#Html.ValidationMessageFor(model => model.LopId, null, new { #class = "help-inline" })
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>
#Ajax.ActionLink("Add", "AddDetails", new AjaxOptions
{
HttpMethod = "GET",
OnSuccess = "successCall",
#*UpdateTargetId = "addDetails",
InsertionMode = InsertionMode.InsertAfter,*#
})
</td>
</tr>
<tr>
<td colspan="6">
#* *#
<input type="submit" value="Lưu thông tin" class="button" />
</td>
</tr>
</tfoot>
</fieldset>
}
</table>
After click Ajax link "Add" it will insert new row to input new data.
Image: http://i808.photobucket.com/albums/zz1/nquangkhaiDST/Postmultipledata_zps5364f0a0.png
The Question is: When I submit to server, it just post the first data, not the data after i click "Add". How i can get all the data even field from ajax to post back to server.
Anyone know how to post all the data even the data of ajax. Thanks a lots
Assuming you'll be adding that same type of object when you click Add, what you need to do is accept an array of your model object in your Post controller parameter.
[HttpPost]
public ActionResult(MyObject[] objects)
{
// do something
}
did you check your html on client side.... while submitting from client side you have to make sure that that the controls added on the page must have naming convention like
<input type="text" value="" name="IncomeDetails[0].IncomeCode" id="IncomeDetails_0__IncomeCode" class="incomeCode valid" disabled="disabled">
on the first row and
<input type="text" disabled="disabled" class="incomeCode valid" id="IncomeDetails_1__IncomeCode" name="IncomeDetails[1].IncomeCode" value="">
on the second row then only while submitting you can get full list of objects.

Partial view renders as full view

MVC 3 , ajax, c#
My partial view is rendering as a new page instead of replacing the search results table.
Controller:
public class SearchController : Controller
{
//
// GET: /Search/
private myEntities db = new myEntities();
private Repository repo = new Repository();
[HttpGet]
public ActionResult Index()
{
var model = new List<PersonViewModel>();
model = repo.GetPeople();
return View(model);
}
public PartialViewResult _SearchResult(string fname, string lname)
{
var personResult = repo.GetSearchResult(fname, lname);
return PartialView("_SearchResult", personResult);
}
}
The view:
<div class="page">
<div class="middle-col-comment-mod">
<h2>Search Existing Trespassers</h2>
<div id="search">
#using (Ajax.BeginForm("_SearchResult", "Search", null, new AjaxOptions { HttpMethod = "Post", InsertionMode = System.Web.Mvc.Ajax.InsertionMode.Replace, UpdateTargetId = "indexSearchResults" }))
{
<div class="editor-field">
<label>First Name:</label>
#Html.TextBox("FirstName")
<label style = "margin-left: 15px;">Last Name:</label>
#Html.TextBox("LastName", "", new { style = "margin-right: 15px;" })
<input type="submit" name="submit" class="skbutton" value="Search" />
</div>
}
</div>
<table id="indexSearchResults" class="data-table">
<tr>
<th>
FirstName
</th>
<th>
LastName
</th>
<th>
Gender
</th>
<th>
City
</th>
<th>
DOB
</th>
<th>
IsStudent
</th>
<th>
Actions
</th>
</tr>
#if (Model.Count() == 0)
{
<tr>
<td colspan=7>
There are currently no trespassers in the trespass database.
</td>
</tr>
}
else
{
foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Gender)
</td>
<td>
#Html.DisplayFor(modelItem => item.DOB)
</td>
<td>
#Html.DisplayFor(modelItem => item.School)
</td>
<td>
#Html.DisplayFor(modelItem => item.IsStudent)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.PersonId }) |
#Html.ActionLink("Details", "Details", new { id = item.PersonId }) |
#Html.ActionLink("Delete", "Delete", new { id = item.PersonId })
</td>
</tr>
}
}
</table>
</div>
</div>
And the partial view:
#model IEnumerable<TrespassTracker.Models.PersonViewModel>
<table>
<tr>
<th>
First Name
</th>
<th>
Last Name
</th>
<th>
Gender
</th>
<th>
Date of Birth
</th>
<th>
Is a Student?
</th>
<th>
Actions
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Gender)
</td>
<td>
#Html.DisplayFor(modelItem => item.DOB)
</td>
<td>
#Html.DisplayFor(modelItem => item.IsStudent)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
</table>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
From my research I found the usual suspect to be the missing link to the jquery script in the partial, but I had that. I checked the network tab on my wed dev tools and found it is being called. What else could the problem be?
the script won't cause any problem and the only thing I see wrong here is the table. you are trying yo fill the table with other table which returns a table, use a div instead to update the ajax form (search result):
<div id="indexSearchResults">
<table>
..........
</table>
</div>
Try this
<div class="page">
<div class="middle-col-comment-mod">
<h2>Search Existing Trespassers</h2>
<div id="search">
#using (Ajax.BeginForm("_SearchResult", "Search", null, new AjaxOptions { HttpMethod = "Post", InsertionMode = System.Web.Mvc.Ajax.InsertionMode.Replace, UpdateTargetId = "indexSearchResults" }))
{
<div class="editor-field">
<label>First Name:</label>
#Html.TextBox("FirstName")
<label style = "margin-left: 15px;">Last Name:</label>
#Html.TextBox("LastName", "", new { style = "margin-right: 15px;" })
<input type="submit" name="submit" class="skbutton" value="Search" />
</div>
}
</div>
#if (Model.Count() == 0)
{
<label>There are currently no trespassers in the trespass database. </label>
}
else
{
foreach (var item in Model)
{
#Html.Partial("__SearchResult",item)
}
</div>
</div>
How 'bout to use jQuery do reload your result content, instead Post from your form? You can named some div with an ID and uses it as reference do jQuery.load() (considering you're using that ViewModel you passed into Index action):
1.View
#model YourModel
<!-- ... -->
<div id="search">
#using (Ajax.BeginForm("MainPostAction", "ControllerName", FormMethod.Post, new { id = "yourFormID" })
{
<div class="editor-field">
<label>First Name:</label>
#Html.TextBoxFor(model => model.FirstName)
<label style = "margin-left: 15px;">Last Name:</label>
#Html.TextBoxFor(model => model.LastName, new { style = "margin-right: 15px;" })
<input type="button" name="submit" id="searchButton" class="skbutton" value="Search" />
</div>
<div id="results"></div>
}
</div>
Javascript:
$(document).ready(function() {
$('#searchButton').click(function(event) {
$('#results').load('#Url.Action('_SearchResult', 'Search')', $('#yourFormID').serialize());
});
}
Your action remains the same.
How 'bout it?

When use IEnumerable in view client side validation is not working?

I am passing List from Model to view , so I specified in view like this
IEnumerable. In this situation Client side validation is not firing
View :
#model IEnumerable<ShoppingCart.Models.ShoppingClass>
#{
ViewBag.Title = "Display";
}
<script src="#Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
#Html.ValidationSummary(true)
#using (Html.BeginForm())
{
<table>
<tr>
<td>#Html.Label("BrandName")
</td>
<td>#Html.TextBox("BrandName")
<div>
#Html.ValidationMessage("BrandName")</div>
</td>
<td>
<input type="submit" value="Search" name="Search" />
</td>
</tr>
</table>
}
What you've written is wrong.
You're got the view strongly typed but then you're not using the strongly typed properties or validation messages. Also, you've got the validation summary outside the form.. which won't work.
#using (Html.BeginForm())
#Html.ValidationSummary(true)
Then, you'll need to do something like this:
<table>
#foreach (ShoppingClass shoppingClass in Model) {
<tr>
<td>#Html.LabelFor(x => x.BrandName)
</td>
<td>#Html.TextBoxFor(x => x.BrandName)
<div>
#Html.ValidationMessageFor(x => x.BrandName)</div>
</td>
</tr>
}
</table>
<input type="submit" value="Search" name="Search" />
I'm not sure why you have a Search button for every item that goes to the same controller and action.. but I'll leave that for you to figure out.

Returning response from a view that contains input type file - Microsoft JScript runtime error: Object expected

I have a simple view that has 2 textboxes and 1 file input.
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage<iLoyalty.BackOfficePortal.Models.SegmentModel>" %>
<% using (Html.BeginForm("SaveSegment", "Segment", FormMethod.Post, new { id = "SegmentForm", enctype = "multipart/form-data" }))
{ %>
<div class="StContent">
<h3>
<%= iLoyalty.BackOfficePortal.Globals.GetResourceText("CardSegmentInsert")%></h3>
<br />
<%= Html.HiddenFor(model => model.ApplicationName, new { id = "ApplicationName" })%>
<%--<%= Html.HiddenFor(model => model.SegmentID, new { id = "SegmentID" })%>--%>
<table width="95%" border="0" cellspacing="1" cellpadding="4" class="Table" style="margin: 0 0 0 10px">
<tr class="Tr0">
<td style="width: 200px" class="Tr1">
<%= iLoyalty.BackOfficePortal.Globals.GetResourceText("ApplicationName")%>
</td>
<td>
<span id="ApplicationName">
<%= Model.ApplicationName %></span>
</td>
</tr>
<tr class="Tr0">
<td style="width: 200px" class="Tr1">
<%= iLoyalty.BackOfficePortal.Globals.GetResourceText("CardSegmentName")%>
</td>
<td>
<%= Html.TextBoxFor(model => model.SegmentName, new { id = "SegmentName", #class = "txtBox" })%>
</td>
</tr>
<tr class="Tr0">
<td style="width: 200px" class="Tr1">
<%= iLoyalty.BackOfficePortal.Globals.GetResourceText("RewardRate")%>
</td>
<td>
<%= Html.TextBoxFor(model => model.GainRate, new { id = "GainRate", #class = "txtBox" })%>
</td>
</tr>
<tr class="Tr0">
<td style="width: 200px" class="Tr1">
</td>
<td>
<input name="PostedFile" id="PostedFile" type="file" class="txtBox" style="width: 200px" />
</td>
</tr>
<tr class="Tr0">
<td class="Tr1" colspan="2" style="text-align: right">
<input id="saveBtn" type="submit" class="button" value='<%= iLoyalty.BackOfficePortal.Globals.GetResourceText("Add")%>' />
</td>
</tr>
</table>
</div>
<script type="text/javascript">
$(document).ready(function () {
$('#saveBtn').click(function () {
//BlockPage();
var options = {
target: '#contentDiv',
success: function () {
BlockDivSuccess('generalCover');
}
};
$('#SegmentForm').ajaxForm(options);
});
});
</script>
<% } %>
After clicking saveBtn I see that in debug mode it posts the appropriate data to the appropriate action and it works well. And in firebug I see the response to the ajax call is just like what I expect to have. But only in ie I get an javascript error that just says:
Microsoft JScript runtime error: Object expected
After I remove the line above, everything is ok in all browsers. But I need this too.
<input name="PostedFile" id="PostedFile" type="file" class="txtBox" style="width: 200px" />
Do you have any idea about this problem? It is interesting that it occurs only in ie.
Thanks in advance,
Just attach your Visual Studio debugger to IE process and then you can see which javascript variable is null.
Open Debug menu, choose Attach to Process..., select iexplore.exe from the list of running processes and click Attach. Make sure, that 'Attach to:' textbox says Script otherwise click Select... button and choose it.
Also make sure that script debugging is not disabled in IE.
See: http://www.jonathanboutelle.com/how-to-debug-javascript-in-internet-explorer

Resources