We just moved an ASP MVC intranet website onto a local server and are experiencing something weird with the pics used on one page. For some reason, the URL contains an extra subfolder. What's weird about this is that this is that it's a URL that's used in the "master template" page, yet no other page is displaying this oddity. This is
Theses are the two pics in question:
<img src="../../Content/images/Monet3.png" id="MonetSig" />
<img src="../../Content/images/TEST2body_top.png" id="topPic" alt="tag"/>
When I bring up the developer tools in Chrome I get the following error messages for both pics:
GET http://insideapps.dev.company.com/Monet/Monet/Content/images/Monet3.png 404 (Not Found)
GET http://insideapps.dev.company.com/Monet/Monet/Content/images/TEST2body_top.png 404 (Not Found)
Again, no other pages display this error.
Here is a copy of the master layout for the site:
<html>
<head>
<meta charset="utf-8" />
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
<script language="javascript">
function DoFun() {
}
</script>
</head>
<body>
#using Monet.Common
<div class="page">
<header>
<div style="margin: 10px;" id="Logo">
<img src="../../Content/images/Monet3.png" id="MonetSig" />
</div>
#* </a>*#
#* <div id="logindisplay">
#Html.Partial("_LogOnPartial")
</div>*#
<nav>
<ul id="menu">
<li>#Html.MenuLink("Agents", "Index", "Agent")</li>
<li>#Html.MenuLink("Products", "Index", "Product")</li>
<li>#Html.MenuLink("Product Training", "Index", "Course")</li>
<li>#Html.MenuLink("Continuing Ed", "Index", "ContEdCourse")</li>
<li>#Html.MenuLink("Help", "About", "Home")</li>
</ul>
</nav>
</header>
<img src="../../Content/images/TEST2body_top.png" id="topPic" alt="tag"/>
<section id="main">
#RenderBody()
</section>
<footer>
</footer>
</div>
</body>
</html>
Just in case, here is the Index.cshtml for the page in question
#model IEnumerable<Monet.Models.FollowUpItems>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<link rel="stylesheet" href="http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css" />
<script src="http://code.jquery.com/jquery-1.8.3.js"></script>
<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
<script src="#Url.Content("~/Scripts/jquery.tablesorter.min.js")" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#thetable").tablesorter();
}
);
function GetNotes(id) {
$('#' + id).dialog();
}
function GetMisc(id) {
var target = id + "Misc";
$('#' + target).dialog();
}
</script>
<h2>Follow Up Items</h2>
#using (Html.BeginForm())
{
<span id="searchBox" class="boxMe" >
<form method="post">
<select name="Table" title="Table" style="font-size:8pt;">
<option value="%">--Table Name--</option>
<option value="AgentContEd">CE</option>
<option value="AgentProductTraining">PT</option>
</select>
<select name="IssueType" style="font-size:8pt;">
<option value="%">--Issue Type--</option>
<option value="W">Warning</option>
<option value="E">Error</option>
</select>
<select name="Status" style="font-size:8pt;">
<option value="%">--Status Type--</option>
<option value="O">Open</option>
<option value="U">Under Review</option>
</select>
<input type="image" src="#Url.Content("~/Content/Images/Filter.bmp")" alt="Filter" style="padding-top: 0px;" />
</form>
</span>
<br />
<br />
<span id="programExplanation" style="width: 500px; float:left; padding: 5px; margin-left: 25px;"></span>
<span class="error" style="clear: both;">
#ViewBag.ErrorMessage
</span>
<span class="msg">
#ViewBag.Message
</span>
<br />
<br />
<br />
}
<table>
<tr>
<th>
Table
</th>
<th>
Issue
</th>
<th>
Status
</th>
<th>
Message
</th>
<th>
CreatedBy
</th>
<th>
CreatedOn
</th>
<th>
Key1
</th>
<th>
Key2
</th>
<th>
Notes
</th>
<th>
Misc.
</th>
<th></th>
</tr>
#foreach (var item in Model.Where(i => i.Status != "C" && i.IssueType != "S"))
{
var note = string.Empty;
if (!String.IsNullOrWhiteSpace(item.Notes))
{
note = item.Notes.ToString();
}
var id = item.Id;
var target = id + "Misc";
<tr>
<td>
#if (!String.IsNullOrWhiteSpace(item.TableName))
{
if (item.TableName.Equals("AgentContEd"))
{
#Html.Raw("CE");
}
else if (item.TableName.Equals("AgentProductTraining"))
{
#Html.Raw("PT");
}
else
{
#Html.DisplayFor(modelItem => item.TableName)
}
}
</td>
<td>
#Html.DisplayFor(modelItem => item.IssueType)
</td>
<td>
#Html.DisplayFor(modelItem => item.Status)
</td>
<td>
#Html.DisplayFor(modelItem => item.Message)
</td>
<td>
#Html.DisplayFor(modelItem => item.CreatedBy)
</td>
<td>
#Html.DisplayFor(modelItem => item.CreatedOn)
</td>
<td>
#Html.DisplayFor(modelItem => item.Key1)
</td>
<td>
#Html.DisplayFor(modelItem => item.Key2)
</td>
<td>
#if (!String.IsNullOrWhiteSpace(item.Notes))
{
<span id="notes" onclick='GetNotes(#id);'>
<img src="#Url.Content("~/Content/images/magnify.gif")" alt="Show Notes" />
</span>
}
<div id="#id" title="Notes" style="display:none;">
#Html.DisplayFor(modelItem => item.Notes)
</div>
</td>
<td>
#if (!String.IsNullOrWhiteSpace(item.LastUpdateBy) || !String.IsNullOrWhiteSpace(item.LastUpdateOn.ToString()))
{
<span id="misc" onclick='GetMisc(#id);'>
<img src="#Url.Content("~/Content/images/magnify.gif")" alt="Show Notes" />
</span>
}
<div id="#target" title="Misc" style="display:none;">
#Html.DisplayFor(modelItem => item.LastUpdateBy)
#Html.DisplayFor(modelItem => item.LastUpdateOn)
</div>
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Id })
</td>
</tr>
}
</table>
Always use heleprs when dealing with urls in an ASP.NET MVC application and never hardcode them as you did.
So:
<img src="#Url.Content("~/Content/images/Monet3.png")" id="MonetSig" />
<img src="#Url.Content("~/Content/images/TEST2body_top.png")" id="topPic" alt="tag" />
and if you are using WebPages v2.0 (which is the default in ASP.NET MVC 4) you could do this:
<img src="~/Content/images/Monet3.png" id="MonetSig" />
<img src="~/Content/images/TEST2body_top.png" id="topPic" alt="tag" />
The Url helper will take care of generating proper url to the resource no matter where and how your application is hosted.
Related
Im trying to submit a form that consist of checkboxes.
When I submit the form I don't get the selected data from the form. I have been trying to use asp-for but I don't understand what I'm doing wrong.
this is my razor page:
#model TheaterReservering.Models.KlantReservering
#{
ViewData["Title"] = "Edit";
}
<h1>Edit</h1>
<h4>Reservering voor: #Model.Klant.Naam</h4>
<form asp-action="Edit">
<input type="hidden" asp-for="Klant" />
<table class="table">
<thead>
<tr>
<th>
1
</th>
<th>
2
</th>
<th>
3
</th>
<th>
4
</th>
<th>
5
</th>
<th>
6
</th>
<th></th>
</tr>
</thead>
<tbody>
#{
var count = 0;
}
#foreach (var item in Model.Reserveringen)
{
if ((count % 6) == 0)
{
#:<tr>
}
<td style="text-align:center; vertical-align:middle">
<div class="form-group">
#if (item.KlantId == Model.Klant.Id)
{
<input type="checkbox" asp-for="Reserveringen.ElementAt(count).Bezet" checked />
<br />
<div style="background-color: blue; text-align: center">
<label style="color:white" asp-for="#item.Naam">#item.Naam</label>
</div>
}
else if (item.KlantId == null)
{
<input type="checkbox" asp-for="Reserveringen.ElementAt(count).Bezet" />
<br />
<div style="background-color: green; text-align: center">
<label style="color:white" asp-for="#item.Naam">#item.Naam</label>
</div>
}
else
{
<input type="checkbox" checked disabled />
<br />
<div style=" background-color: red; text-align: center">
<label style="color:white" asp-for="#item.Naam">#item.Naam</label>
</div>
}
</div>
</td>
if ((count % 6) == 5)
{
#:</tr>
}
count++;
}
</tbody>
</table>
<div class="form-group">
<input type="submit" value="Reserveringen vastleggen" class="btn btn-primary" />
</div>
</form>
My controller methode:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Klant,Reserveringen")] KlantReservering klantReservering)
{
if (id != klantReservering.Klant.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
_context.Update(klantReservering);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(klantReservering);
}
and this is the class i created to combine the class Klant with Reservering.
public class KlantReservering
{
public Klant Klant { get; set; }
public List<Reservering> Reserveringen { get; set; }
}
}
As far as I know, the tag helper couldn't work with a model class, it could only work for the model's property.
That means we couldn't use tag helper like this <input type="hidden" asp-for="Klant" />. If we want to achieve model binding in the controller method. I suggest you could add all the property as below:
<input type="hidden" asp-for="#Model.Klant.Id" />
<input type="hidden" asp-for="#Model.Klant.Naam" />
Besides, for the foreach item, tag helper couldn't figure out what the "Reserveringen.ElementAt(count).Bezet" means, we could only use this "#Model.Reserveringen[count].Bezet".
More details, you could refer to below example view:
Notice: Since I don't know your details codes about the Klant and the Reserveringen class, I created a test class in my side which just contains Naam and Id property.
#model CoreNormalIssue.Models.KlantReservering
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
#*
For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
*#
#{
ViewData["Title"] = "Edit";
}
<h1>Edit</h1>
<h4>Reservering voor: #Model.Klant.Naam</h4>
<form asp-controller="Verify" asp-action="Edit" method="post" asp-route-id="#Model.Klant.Id">
<input type="hidden" asp-for="#Model.Klant.Id" />
<input type="hidden" asp-for="#Model.Klant.Naam" />
<table class="table">
<thead>
<tr>
<th>
1
</th>
<th>
2
</th>
<th>
3
</th>
<th>
4
</th>
<th>
5
</th>
<th>
6
</th>
<th></th>
</tr>
</thead>
<tbody>
#{
var count = 0;
}
#foreach (var item in Model.Reserveringen)
{
<input type="text" asp-for="#item.Bezet" />
if ((count % 6) == 0)
{
#:<tr>
}
<td style="text-align:center; vertical-align:middle">
<div class="form-group">
#if (item.KlantId == Model.Klant.Id)
{
<input type="checkbox" asp-for="#Model.Reserveringen[count].Bezet" checked />
<br />
<div style="background-color: blue; text-align: center">
<label style="color:white" asp-for="#item.Naam">#item.Naam</label>
</div>
}
else if (item.KlantId == null)
{
<input type="checkbox" asp-for="#Model.Reserveringen[count].Bezet" />
<br />
<div style="background-color: green; text-align: center">
<label style="color:white" asp-for="#item.Naam">#item.Naam</label>
</div>
}
else
{
<input type="checkbox" checked disabled />
<br />
<div style=" background-color: red; text-align: center">
<label style="color:white" asp-for="#item.Naam">#item.Naam</label>
</div>
}
</div>
</td>
if ((count % 6) == 5)
{
#:</tr>
}
count++;
}
</tbody>
</table>
<div class="form-group">
<input type="submit" value="Reserveringen vastleggen" class="btn btn-primary" />
</div>
</form>
Result:
This is the third question on this topic. Hopefully I’ve improved the question as I struggle with wrapping up this project. First, let’s look at the page with the Dropdown list of Alert_Identifiers—the key value that gets data from the mysql database for the project. AlertPick.cshtml:
#model IEnumerable<edxl_cap_v1_2.Models.ContentViewModels.Alert>
#using edxl_cap_v1_2.Models.ContentViewModels
#{
ViewData["Title"] = "PickAlert";
}
<head>
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="~/css/capv1_2_refimp.css" />
<title>#ViewBag.Title</title>
</head>
<h4>Alert</h4>
<div>
#ViewBag.Message
</div>
<style>
tr:nth-child(even) {
background-color: lightBlue;
}
tr:nth-child(odd) {
background-color: white;
}
</style>
<table class="smallText">
#foreach (var item in Model)
{
<tr>
<td>
</td>
<td>
<div id="elementInput">
<span class="smallText">
#Html.DisplayNameFor(model => model.Alert_Identifier) value
<input type="text" name="elementValue" value="#Html.DisplayFor(modelItem => item.Alert_Identifier)" size="60" />
</span>
</div>
</td>
<td>
<text> </text>
</td>
<td>
<form asp-area="" asp-controller="alerts" asp-action="_DetailsAlert" method="post" asp-route-id="#item.AlertIndex">
<input type="hidden"
name="Identifier"
value="#Html.DisplayFor(modelItem => item.Alert_Identifier)">
<input type="submit"
value="Check Alert">
</form>
</td>
<td>
<text> </text>
</td>
</tr>
<tr>
<td>
</td>
<td>
<div id="elementInput">
<span class="smallText">
#Html.DisplayNameFor(model => model.Alert_Identifier) value
<input type="text" name="elementValue" value="#Html.DisplayFor(modelItem => item.Alert_Identifier)" size="60" />
</span>
</div>
</td>
<td>
<text> </text>
</td>
<td>
<form asp-area="" asp-controller="infos" asp-action="_DetailsInfo" method="post" asp-route-id="#item.AlertIndex">
<input type="hidden"
name="Identifier"
value="#Html.DisplayFor(modelItem => item.Alert_Identifier)">
<input type="submit"
value="Check Info">
</form>
</td>
<td>
<text> </text>
</td>
</tr>
<tr>
<td>
</td>
<td>
<div id="elementInput">
<span class="smallText">
#Html.DisplayNameFor(model => model.Alert_Identifier) value
<input type="text" name="elementValue" value="#Html.DisplayFor(modelItem => item.Alert_Identifier)" size="60" />
</span>
</div>
</td>
<td>
<text> </text>
</td>
<td>
<form asp-area="" asp-controller="areas" asp-action="_DetailsArea" method="post" asp-route-id="#item.AlertIndex">
<input type="hidden"
name="Identifier"
value="#Html.DisplayFor(modelItem => item.Alert_Identifier)">
<input type="submit"
value="Check Area">
</form>
</td>
<td>
<text> </text>
</td>
</tr>
<tr>
<td>
</td>
<td>
<div id="elementInput">
<span class="smallText">
#Html.DisplayNameFor(model => model.Alert_Identifier) value
<input type="text" name="elementValue" value="#Html.DisplayFor(modelItem => item.Alert_Identifier)" size="60" />
</span>
</div>
</td>
<td>
<text> </text>
</td>
<td>
<form asp-area="" asp-controller="resources" asp-action="_DetailsResource" method="post" asp-route-id="#item.AlertIndex">
<input type="hidden"
name="Identifier"
value="#Html.DisplayFor(modelItem => item.Alert_Identifier)">
<input type="submit"
value="Check Resource">
</form>
</td>
<td>
<text> </text>
</td>
</tr>
<tr>
<td>
</td>
<td>
<div id="elementInput">
<span class="smallText">
#Html.DisplayNameFor(model => model.Alert_Identifier) value
<input type="text" name="elementValue" value="#Html.DisplayFor(modelItem => item.Alert_Identifier)" size="60" />
</span>
</div>
</td>
<td>
<text> </text>
</td>
<td>
<form asp-area="" asp-controller="EdxlCapMessageViewModels" asp-action="_Assemble" method="post" asp-route-id="#item.AlertIndex">
<input type="hidden"
name="Identifier"
value="#Html.DisplayFor(modelItem => item.Alert_Identifier)">
<input type="submit"
value="Add All">
</form>
</td>
<td>
<text> </text>
</td>
</tr>
}
</table>
Once the Alert_Identifier that corresponds to one record in the database is selected and the submit button is clicked, the browser opens this page
The first four rows work correctly when the “Check XXX” submit button is clicked. They show the individual data category “_DetailsXXX.cshtml” page one at a time. Here is the screen of the page showing the _DetailsAlert.cshtml page.
This is set up so that these pages can be reviewed individually and the composite page, once working, will also work in the “Review” page and the “Approve” page. In the case of the “Assemble” page here, the four individual pages are intended to appear composited together when the “Add All” submit button is clicked, but currently these pages appear without data values for the data items.
I am also going to ping a couple of more experienced people who have helped me previously to take a look at this, I am also studying a wholly different injection mechanism for injecting data into the program where needed which I will consider using in the follow-on specfications.
Lastly, I am rexbroo at GitHub.com where you can find nearly identical Visual Studio programs in the repos: edxl_cap_v1_2-VS4Win (for Windows) and edxl_cap_v1_2-VS4Mac (for Mac) and edxl_cap_v1_2,sql-mysql-VisualStudio where the most current dump of the database is 20180928.
<input type="text" name="elementValue" value="#Html.DisplayFor(modelItem => item.Alert_Identifier)" size="60" />
You don't need to use the #Html.DisplayFor helper here. Just use:
<input type="text" name="elementValue" value="#item.Alert_Identifier" size="60" />
None of your input values should be using the Html.DisplayFor. That is inserting a tag into the value when all you really want is the value of the property.
Also, I question the reason for using multiple forms on a page. Could you use a single form and post to a single action? Do you need to post at all? Could the action be refactored into a get and let you use a <a> tag instead?
I have a question , I have in my view a form, this form contains a list , this list contains four attributes , vendor , application , product and value , these 4 we display only two ( as seen in the code) would like to display in a modal product and the value of the order , the list is displayed in the same position already has such data , how do I display that data through an action of my button that has the action " getFornecedor " ( this action has not yet been implemented , I do not know if it is necessary because the elements are in the same position in the list )
View
#model Test.Models.Order
<head>
<meta charset="utf-8" />
<title>Teste</title>
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<link rel="stylesheet" href="/resources/demos/style.css">
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="http://cdn.datatables.net/1.10.2/css/jquery.dataTables.min.css">
<script type="text/javascript" src="http://cdn.datatables.net/1.10.2/js/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
#Styles.Render("~/Content/bootstrap.css")
#Scripts.Render("~/bundles/modernizr")
<style>
th {
height: 10px;
}
</style>
</head>
<body>
<div id="divbody">
<nav class="navbar navbar-inverse">
</nav>
#using (Html.BeginForm("Save", "Cab", FormMethod.Post))
{
<div class="table-responsive" id="table">
<table id="myTable" class="table table-striped" cellspacing="0">
<thead style="position:static">
<tr>
<th style="font-size:10px">SELECT</th>
<th style="font-size:10px">CONTACT</th>
<th></th>
<th style="font-size:10px">SUPPLY</th>
<th style="font-size:10px">ORDER</th>
</tr>
</thead>
#for (int i = 0; i < Model.listOrder.Count(); i++)
{
<tr>
<td align="center" height="2px">#Html.CheckBoxFor(m => m.listOrder[i].isEdit, new { #onclick = "habilit(" + i + ")", #id = "c" + i })</td>
<td colspan="2">
<a href="#Url.Action("getFornecedor", "MyController")" class="btn btn-xs btn-primary">
<i class="glyphicon glyphicon-phone-alt"></i>
</a>
<a href="#Url.Action("sendEmail", "MyController")" class="btn btn-xs btn-primary">
<i class="glyphicon glyphicon-envelope"></i>
</a>
</td>
<td height="2px"> #Html.TextBoxFor(m => m.listOrder[i].supply, new { #readonly = "readonly", #size = "18px", #class = "form-controlSupply" }) </td>
<td height="2px"> #Html.TextBoxFor(m => m.listOrder[i].order, new { #readonly = "readonly", #size = "75px", #class = "form-controlOrder" }) </td>
<td></td>
</tr>
}
</table>
</div>
<br />
<input type="submit" value="Salve" id="btn" disabled="disabled" class="btn btn-small btn-primary" />
}
</div>
</body>
</html>
MVC doesn`t have modal on fly .. (like control in web forms for example) i suggest you to use third party library , may be something like jquery UI .. You can see example here : https://jqueryui.com/dialog/
You just need client side event to show modal dialog. In that container you can put any data that you want.
It may be the easiest question but I am not able to resolve this. The validation on my page is not working. Everytime I am submitting the page leaving all the input fields blank, an alert is generated saying 'Failed'. And if I enter all the fields with some value data is successfully submitted.
Here is my HTML :
#{
ViewBag.Title = "Exercise10";
}
<html>
<head>
<script src="../../Scripts/jquery-1.6.2.js" type="text/javascript"></script>
<script src="../../Scripts/knockout-2.2.1.js" type="text/javascript"></script>
<script src="../../Scripts/knockout.mapping-latest.js" type="text/javascript"></script>
<script src="../../Scripts/json2.js" type="text/javascript"></script>
<link href="../../Content/ExerciseStyle.css" rel="stylesheet" type="text/css" />
<script src="../../Scripts/Popup.js" type="text/javascript"></script>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.0/themes/base/jquery- ui.css" />
<script src="http://code.jquery.com/ui/1.10.0/jquery-ui.js"></script>
<script src="../../Scripts/DatePicker.js" type="text/javascript"></script>
<script src="../../Scripts/knockout.validation.js" type="text/javascript"></script>
<script src="../../Scripts/knockout-validator.js" type="text/javascript"></script>
<script src="../../Scripts/knockout-validator-extensions.js" type="text/javascript"></script>
<link href="../../Scripts/extensions.css" rel="stylesheet" type="text/css" />
</head>
<body>
<form action="" method="post">
<div id="MainArea">
<table id="tbllist" align="center" style="margin-left: 15px; width: 96%; margin- right: 15px;">
<tr>
<th colspan="3" align="left">
<div id="title_p">
Enter Following Entries</div>
</th>
</tr>
<tr>
<td align="right" style="width: 40%;">
<b>Name :</b>
</td>
<td align="left" style="width: 17%;">
<input data-bind="value: EmployeeName" placeholder="Employee Name" class="txt"
type="text" />
</td>
<td align="left">
</td>
</tr>
<tr>
<td align="right">
<b>Emp# :</b>
</td>
<td align="left">
<input data-bind="value: EmployeeCode" placeholder="Employee Code" style="width: 200px;"
type="text" />
</td>
<td align="left">
</td>
</tr>
<tr>
<td align="right">
<b>Date of Birth :</b>
</td>
<td align="left">
<input data-bind="value: Dob" id="datepicker" placeholder="Date of Birth" style="width: 200px;"
type="text" /><span>(dd/mm/yyyy)</span>
</td>
<td align="left">
</td>
</tr>
<tr>
<td align="right">
<b>Age (18-60):</b>
</td>
<td align="left">
<input data-bind="value: Age" style="width: 200px;" placeholder="Age Range (18-60)"
type="number" min="18" max="60" />
</td>
<td align="left">
</td>
</tr>
<tr>
<td align="right">
<b>Contact Number :</b>
</td>
<td align="left">
<input data-bind="value: ContactNumber" placeholder="Contact Number" style="width: 200px;"
type="text" />
</td>
<td align="left">
</td>
</tr>
<tr>
<td align="right">
<b>Email :</b>
</td>
<td align="left">
<input data-bind="value: EmailID" placeholder="Email ID" style="width: 200px;"
type="email" />
</td>
<td align="left">
</td>
</tr>
<tr>
<td align="right">
<b>Address :</b>
</td>
<td align="left">
<input data-bind="value: Address" placeholder="Address" style="width: 200px;"
type="text" />
</td>
<td align="left">
</td>
</tr>
<tr>
<td align="right">
<b>City :</b>
</td>
<td align="left">
<select data-bind="value: City" style="width: 200px;">
<option value="Noida">New Delhi</option>
<option value="Noida">Noida</option>
<option value="Noida">Mumbai</option>
</select>
</td>
<td align="left">
</td>
</tr>
<tr>
<td align="right">
<b>Marital Status :</b>
</td>
<td align="left">
<input data-bind="checked: MaritalStatus" checked="checked" name="rdb" type="radio" /><span>UnMarried</span>
<input data-bind="checked: MaritalStatus" checked="checked" name="rdb" type="radio" checked="checked" /><span>Married</span>
</td>
<td align="left">
</td>
</tr>
<tr>
<td align="right">
<b>Any Employee Reference :</b>
</td>
<td align="left">
<input data-bind="checked: Is_Reference" type="checkbox" />yes
</td>
<td align="left">
</td>
</tr>
</table>
<table style="width: 99%; margin-right: 20px; padding: 5px;">
<tr align="right">
<td>
<button data-bind="click :$root.save" class="button">Save</button>
<input type="button" id="btnCancel" class="button" value="Cancel" onclick="JavaScript:closePopup();" />
</td>
</tr>
</table>
</div>
</form>
And My View Model (continued from the above):
<script type="text/javascript">
//....................................................//
var EmpViewModel = function () {
//Make the self as 'this' reference
var self = this;
//Declare observable which will be bind with UI
self.EmployeeCode = ko.observable("").extend({ required: true });
self.EmployeeName = ko.observable("").extend({ required: { message: 'Please supply your Name.'} });
self.Dob = ko.observable("");
self.Age = ko.observable("").extend({number :true});
self.ContactNumber = ko.observable("");
self.EmailID = ko.observable("");
self.Address = ko.observable("");
self.MaritalStatus = ko.observable("");
self.City = ko.observable("");
self.Is_Reference = ko.observable("");
//The Object which stored data entered in the observables
var EmpData = {
EmpCode: self.EmployeeCode,
EmpName: self.EmployeeName,
Dob: self.Dob,
Age: self.Age,
ContactNumber: self.ContactNumber,
MaritalStatus: self.MaritalStatus,
EmailID: self.EmailID,
Address: self.Address,
City: self.City,
Is_Reference: self.Is_Reference
};
//Declare an ObservableArray for Storing the JSON Response
self.Employees = ko.observableArray([]);
//Function to perform POST (insert Employee) operation
self.save = function () {
//Ajax call to Insert the Employee
$.ajax({
type: "POST",
url: "/Exercise/Save/",
data: ko.toJSON(this), //Convert the Observable Data into JSON
contentType: "application/json",
success: function (data) {
alert(data);
},
error: function () {
alert("Failed");
}
});
//Ends Here
};
}
ko.applyBindings(new EmpViewModel());
</script>
Knockout-validation shows validation messages only if the fields are modified. Therefore you should check on submit if all fields are valid and show all errors if not.
self.errors = ko.validation.group(this, { deep: true, observable: false });
//Function to perform POST (insert Employee) operation
self.save = function () {
// check if valid
if(self.errors().length > 0) {
self.errors.showAllMessages();
return;
}
//Ajax call to Insert the Employee
$.ajax({
type: "POST",
url: "/Exercise/Save/",
data: ko.toJSON(this), //Convert the Observable Data into JSON
contentType: "application/json",
success: function (data) {
alert(data);
},
error: function () {
alert("Failed");
}
});
//Ends Here
};
I have created a fiddle to show that: http://jsfiddle.net/delixfe/tSzYf/2/
There is a lot to commend MVC, but one problem I keep getting is ID name collisions.
I first noticed it when generating a grid using a foreach loop. With the help of SO I found the solution was to use Editor Templates.
Now I have the same problem with tabs.
I used this reference to find out how to use tabs; http://blog.roonga.com.au/search?updated-max=2010-06-14T19:27:00%2B10:00&max-results=1
The problem with my tabs is that I am using a date field with a date picker. In the example above, ID name collisions are avoided by referencing a generated unique Id of the container element. However for a datepicker, the ID of the container is irrelevant, only the ID of the date field matters. So what happens is that if I create my second tab the same as the first, when I update my second tab, the date on the first is updated.
So below is my View, and a partial view which displays the date. When I click the "Add Absence for 1 day button, I create a tab for that screen;
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/AdminAccounts.master"
Inherits="System.Web.Mvc.ViewPage<SHP.WebUI.Models.AbsenceViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
AbsenceForEmployee
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="AdminAccountsContent" runat="server">
<script type="text/javascript">
$(function () {
$('#tabs').tabs(
{ cache: true },
{
ajaxOptions: {
cache: false,
error: function (xhr, status, index, anchor) {
$(anchor.hash).html("Couldn't load this tab.");
},
data: {},
success: function (data, textStatus) { }
},
add: function (event, ui) {
//select the new tab
$('#tabs').tabs('select', '#' + ui.panel.id);
}
});
});
function addTab(title, uri) {
var newTab = $("#tabs").tabs("add", uri, title);
}
function closeTab() {
var index = getSelectedTabIndex();
$("#tabs").tabs("remove", index)
}
function getSelectedTabIndex() {
return $("#tabs").tabs('option', 'selected');
}
function RefreshList() {
$('#frmAbsenceList').submit();
}
</script>
<% using (Html.BeginForm()) {%>
<%: Html.AntiForgeryToken() %>
<fieldset>
<legend>Select an employee to edit absence record</legend>
<div style="padding-bottom:30px;padding-left:10px;">
<div class="span-7"><b>Name:</b> <%: Model.Employee.GetName() %></div>
<div class="span-6"><b>Division:</b><%: Model.DivisionName %></div>
<div class="span-6"><b>Department:</b> <%: Model.DepartmentName %></div></div>
<p>Attendance record for the year <%: Html.DropDownListFor(model => model.SelectedYearId, Model.YearList, new { onchange = "this.form.submit();" })%></p>
<div id="tabs">
<ul>
<li>Absence List</li>
</ul>
<div id="tabs-1">
<input id="btnAddOneDayTab" type="button" onclick="addTab('Add Absence (1 day)','<%= Url.Action("AddAbsenceOneDay", "Employee") %>')" value='Add Absence for 1 day' />
<input id="btnAddDateRangeTab" type="button" onclick="addTab('Add Absence (date range)','<%= Url.Action("AddAbsenceDateRange", "Employee") %>')" value='Add Absence for a range of dates' />
<hr />
<% Html.RenderPartial("ListAbsence", Model.ListEmployeeAbsenceThisYear); %>
</div>
</div>
</fieldset>
<% } %>
Add new date partial view ...
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SHP.Models.EmployeeOtherLeaf>" %>
<% var unique = DateTime.Now.Ticks.ToString(); %>
<script language="javascript" type="text/javascript">
$(document).ready(function () {
$('#frmAddAbsenceOneDay<%= unique %> #NullableOtherLeaveDate').datepicker({ dateFormat: 'dd-MM-yy' });
$('#frmAddAbsenceOneDay<%= unique %> #MorningOnlyFlag').click(function () {
$('#frmAddAbsenceOneDay<%= unique %> #AfternoonOnlyFlag').attr('checked', false);
})
$('#frmAddAbsenceOneDay<%= unique %> #AfternoonOnlyFlag').click(function () {
$('#frmAddAbsenceOneDay<%= unique %> #MorningOnlyFlag').attr('checked', false);
})
});
var options = {
target: '#frmAddAbsenceOneDay<%= unique %>',
success: RefreshList
};
$(document).ready(function () {
$('#frmAddAbsenceOneDay<%= unique %>').ajaxForm(options);
});
</script>
<div id="AddAbsenceOnDay<%= unique %>">
<% using (Html.BeginForm("AddAbsenceOneDay", "Employee", FormMethod.Post,
new { id = "frmAddAbsenceOneDay" + unique }))
{ %>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Add an absence for a day or half day</legend>
<table>
<tr>
<td><%: Html.LabelFor(model => model.OtherLeaveId)%></td>
<td>
<%: Html.DropDownListFor(model => model.OtherLeaveId, Model.SelectLeaveTypeList, "<--Select-->")%>
<%: Html.ValidationMessageFor(model => model.OtherLeaveId)%>
</td>
</tr>
<tr>
<td>
<%: Html.LabelFor(model => model.NullableOtherLeaveDate)%>
</td>
<td>
<%: Html.EditorFor(model => model.NullableOtherLeaveDate)%>
<%: Html.ValidationMessageFor(model => model.NullableOtherLeaveDate)%>
<%if (ViewData["ErrorDateMessage"] != null && ViewData["ErrorDateMessage"].ToString().Length > 0)
{ %>
<p class="error">
At <% Response.Write(DateTime.Now.ToString("T")); %>. <%: ViewData["ErrorDateMessage"]%>.
</p>
<%} %>
</td>
</tr>
<tr>
<td>
<%: Html.LabelFor(model => model.MorningOnlyFlag)%>
</td>
<td>
<%: Html.CheckBoxFor(model => model.MorningOnlyFlag)%>
<%: Html.ValidationMessageFor(model => model.MorningOnlyFlag)%>
</td>
</tr>
<tr>
<td>
<%: Html.LabelFor(model => model.AfternoonOnlyFlag)%>
</td>
<td>
<%: Html.CheckBoxFor(model => model.AfternoonOnlyFlag)%>
<%: Html.ValidationMessageFor(model => model.AfternoonOnlyFlag)%>
</td>
</tr>
</table>
<p>
<span style="padding-right:10px;"><input type="submit" value="Create" /></span><input type="button" value="Close" onclick="closeTab()" />
</p>
</fieldset>
<% } %>
</div>
You can see the ID of the date in the following HTML from Firebug
<div id="main">
<div id="adminAccounts">
<table>
<tbody><tr>
<td>
<div style="padding-top: 15px;">
// Menu removed
</div>
</td>
<td>
<script type="text/javascript">
$(function () {
$('#tabs').tabs(
{ cache: true },
{
ajaxOptions: {
cache: false,
error: function (xhr, status, index, anchor) {
$(anchor.hash).html("Couldn't load this tab.");
},
data: {},
success: function (data, textStatus) { }
},
add: function (event, ui) {
//select the new tab
$('#tabs').tabs('select', '#' + ui.panel.id);
}
});
});
function addTab(title, uri) {
var newTab = $("#tabs").tabs("add", uri, title);
}
function closeTab() {
var index = getSelectedTabIndex();
$("#tabs").tabs("remove", index)
}
function getSelectedTabIndex() {
return $("#tabs").tabs('option', 'selected');
}
function RefreshList() {
$('#frmAbsenceList').submit();
}
</script>
<form method="post" action="/Employee/AbsenceForEmployee?employeeId=1"><input type="hidden" value="8yGn2w+fgqSRsho/d+7FMnPWBtTbu96X4u1t/Jf6+4nDSNJHOPeq7IT9CedAjrZIAK/DgbNX6idtTd94XUBM5w==" name="__RequestVerificationToken">
<fieldset>
<legend>Select an employee to edit absence record</legend>
<div style="padding-bottom: 30px; padding-left: 10px;">
<div class="span-7"><b>Name:</b> xaviar caviar</div>
<div class="span-6"><b>Division:</b>ICT</div>
<div class="span-6"><b>Department:</b> ICT</div></div>
<p>Absence Leave record for the year <select onchange="this.form.submit();" name="SelectedYearId" id="SelectedYearId"><option value="2" selected="selected">2010/11</option>
</select></p>
<div id="tabs" class="ui-tabs ui-widget ui-widget-content ui-corner-all">
<ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all">
<li class="ui-state-default ui-corner-top">Absence List</li>
<li class="ui-state-default ui-corner-top"><span>Add Absence (1 day)</span></li><li class="ui-state-default ui-corner-top ui-tabs-selected ui-state-active"><span>Add Absence (1 day)</span></li></ul>
<div id="tabs-1" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide">
<input type="button" value="Add Absence for 1 day" onclick="addTab('Add Absence (1 day)','/Employee/AddAbsenceOneDay')" id="btnAddOneDayTab">
<input type="button" value="Add Absence for a range of dates" onclick="addTab('Add Absence (date range)','/Employee/AddAbsenceDateRange')" id="btnAddDateRangeTab">
<hr>
<script type="text/javascript">
var options = {
target: '#AbsenceList'
};
$(document).ready(function() {
$('#frmAbsenceList').ajaxForm(options);
});
</script>
<div id="AbsenceList">
<table class="grid"><thead><tr><th class="sort_asc"></th><th>Leave Type</th><th>Morning Only</th><th>Afternoon Only</th><th>Day Amount</th><th>Date</th></tr></thead><tbody><tr class="gridrow"><td>Delete</td><td>Sickness</td><td>False</td><td>False</td><td>1</td><td>04/11/2010</td></tr><tr class="gridrow_alternate"><td>Delete</td><td>Unpaid Sickness</td><td>False</td><td>False</td><td>1</td><td>08/11/2010</td></tr><tr class="gridrow"><td>Delete</td><td>Unpaid Compassionate</td><td>False</td><td>False</td><td>1</td><td>09/11/2010</td></tr><tr class="gridrow_alternate"><td>Delete</td><td>Compassionate</td><td>False</td><td>False</td><td>1</td><td>10/11/2010</td></tr><tr class="gridrow"><td>Delete</td><td>Compassionate</td><td>False</td><td>False</td><td>1</td><td>15/11/2010</td></tr><tr class="gridrow_alternate"><td>Delete</td><td>Unpaid Sickness</td><td>False</td><td>False</td><td>1</td><td>16/11/2010</td></tr><tr class="gridrow"><td>Delete</td><td>Compassionate</td><td>False</td><td>False</td><td>1</td><td>17/11/2010</td></tr><tr class="gridrow_alternate"><td>Delete</td><td>Compassionate</td><td>False</td><td>False</td><td>1</td><td>22/11/2010</td></tr><tr class="gridrow"><td>Delete</td><td>Unpaid Sickness</td><td>False</td><td>False</td><td>1</td><td>24/11/2010</td></tr><tr class="gridrow_alternate"><td>Delete</td><td>Sickness</td><td>False</td><td>False</td><td>1</td><td>25/11/2010</td></tr><tr class="gridrow"><td>Delete</td><td>Unpaid Sickness</td><td>False</td><td>False</td><td>1</td><td>26/11/2010</td></tr><tr class="gridrow_alternate"><td>Delete</td><td>Unpaid Sickness</td><td>False</td><td>False</td><td>1</td><td>29/11/2010</td></tr><tr class="gridrow"><td>Delete</td><td>Compassionate</td><td>False</td><td>False</td><td>1</td><td>30/11/2010</td></tr><tr class="gridrow_alternate"><td>Delete</td><td>Unpaid Sickness</td><td>False</td><td>False</td><td>1</td><td>13/12/2010</td></tr><tr class="gridrow"><td>Delete</td><td>Compassionate</td><td>False</td><td>False</td><td>1</td><td>26/12/2010</td></tr></tbody></table>
<p></p><div class="pagination"><span class="paginationLeft">Showing 1 - 15 of 21 </span><span class="paginationRight">first | prev | next | last</span></div>
</div>
</div><div id="ui-tabs-2" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide">
<div id="AddAbsenceOnDay634255177533718544">
<form method="post" id="frmAddAbsenceOneDay634255177533718544" action="/Employee/AddAbsenceOneDay">
<fieldset>
<legend>Add an absence for a day or half day</legend>
<table>
<tbody><tr>
<td><label for="OtherLeaveId">Leave Type</label></td>
<td>
<select name="OtherLeaveId" id="OtherLeaveId"><option value=""><--Select--></option>
<option value="1">Sickness</option>
<option value="2">Unpaid Sickness</option>
<option value="6">Compassionate</option>
<option value="7">Unpaid Compassionate</option>
<option value="8">Unauthorised</option>
<option value="9">Unpaid Unauthorised</option>
<option value="10">Other</option>
<option value="11">Unpaid Other</option>
</select>
</td>
</tr>
<tr>
<td>
<label for="NullableOtherLeaveDate">Date</label>
</td>
<td>
<input type="text" value="" name="NullableOtherLeaveDate" id="NullableOtherLeaveDate" class="datePicker hasDatepicker">
</td>
</tr>
<tr>
<td>
<label for="MorningOnlyFlag">Morning Only</label>
</td>
<td>
<input type="checkbox" value="true" name="MorningOnlyFlag" id="MorningOnlyFlag"><input type="hidden" value="false" name="MorningOnlyFlag">
</td>
</tr>
<tr>
<td>
<label for="AfternoonOnlyFlag">Afternoon Only</label>
</td>
<td>
<input type="checkbox" value="true" name="AfternoonOnlyFlag" id="AfternoonOnlyFlag"><input type="hidden" value="false" name="AfternoonOnlyFlag">
</td>
</tr>
</tbody></table>
<p>
<span style="padding-right: 10px;"><input type="submit" value="Create"></span><input type="button" onclick="closeTab()" value="Close">
</p>
</fieldset>
</form>
</div>
</div><div id="ui-tabs-4" class="ui-tabs-panel ui-widget-content ui-corner-bottom">
<div id="AddAbsenceOnDay634255177583860349">
<form method="post" id="frmAddAbsenceOneDay634255177583860349" action="/Employee/AddAbsenceOneDay">
<fieldset>
<legend>Add an absence for a day or half day</legend>
<table>
<tbody><tr>
<td><label for="OtherLeaveId">Leave Type</label></td>
<td>
<select name="OtherLeaveId" id="OtherLeaveId"><option value=""><--Select--></option>
<option value="1">Sickness</option>
<option value="2">Unpaid Sickness</option>
<option value="6">Compassionate</option>
<option value="7">Unpaid Compassionate</option>
<option value="8">Unauthorised</option>
<option value="9">Unpaid Unauthorised</option>
<option value="10">Other</option>
<option value="11">Unpaid Other</option>
</select>
</td>
</tr>
<tr>
<td>
<label for="NullableOtherLeaveDate">Date</label>
</td>
<td>
<input type="text" value="" name="NullableOtherLeaveDate" id="NullableOtherLeaveDate" class="datePicker hasDatepicker">
</td>
</tr>
<tr>
<td>
<label for="MorningOnlyFlag">Morning Only</label>
</td>
<td>
<input type="checkbox" value="true" name="MorningOnlyFlag" id="MorningOnlyFlag"><input type="hidden" value="false" name="MorningOnlyFlag">
</td>
</tr>
<tr>
<td>
<label for="AfternoonOnlyFlag">Afternoon Only</label>
</td>
<td>
<input type="checkbox" value="true" name="AfternoonOnlyFlag" id="AfternoonOnlyFlag"><input type="hidden" value="false" name="AfternoonOnlyFlag">
</td>
</tr>
</tbody></table>
<p>
<span style="padding-right: 10px;"><input type="submit" value="Create"></span><input type="button" onclick="closeTab()" value="Close">
</p>
</fieldset>
</form>
</div>
</div>
<div id="ui-tabs-1" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"></div><div id="ui-tabs-3" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"></div></div>
</fieldset>
</form></td>
</tr>
</tbody></table></div>
<div id="footer">
</div>
</div>
If you have got this far(!), I have been asked for the controller, so here it is.
[Authorize(Roles = "Administrator, AdminAccounts, ManagerAccounts")]
public ActionResult AddAbsenceOneDay()
{
return View(new EmployeeOtherLeaf());
}
[HttpPost]
[Authorize(Roles = "Administrator, AdminAccounts, ManagerAccounts")]
public ActionResult AddAbsenceOneDay(EmployeeOtherLeaf _absence)
{
if (ModelState.IsValid)
{
_absence.EmployeeId = SessionObjects.EmployeeId;
_absence.OtherLeaveDate = _absence.NullableOtherLeaveDate.GetValueOrDefault(DateTime.Today);
Tuple<bool, string> errorInfo = _absence.IsDateValid();
if (errorInfo.Item1 == true)
{
_absence.AddAndSave();
ViewData["SuccessMessage"] = "Successfully Added.";
return View("EditAbsenceOneDay", _absence);
}
else
{
ViewData["ErrorDateMessage"] = errorInfo.Item2;
return View(_absence);
}
}
else
{
return View(_absence);
}
}
The problem seems to be that the DOM only has one entry for NullableOtherLeaveDate. This seems logical because of the use of ID. What you can to is add the hash to the ID as well. If you need to match that ID with any jQuery you can use partial selectors like this:
$('input[id*=NullableOtherLeaveDate]')
See jQuery Partial Selectors for more about that.
Now how the modal binder will bind that I'm not sure but you can probably implement partial matching in C# with no problems. If you want any help with this please post the relevant code of your action.
The answer to this other question suggests using editor templates instead of partials to solve the problem.
MVC - fields in a partial View need a Unique Id. How do you do this?
Of course this will not work for every situations, just the editor ones.
Update:
There is another easy way too. The ViewData has a nice property you can use to set a prefix that makes the partial unique, then this ViewDataDictonary can be passed to the partial.
var dataDictionary = new ViewDataDictionary<PersonModel>(Model.Persons.First);
dataDictionary.TemplateInfo.HtmlFieldPrefix = "Persons.First";
See the following links for details on this:
- http://forums.asp.net/t/1627585.aspx/1
- http://forums.asp.net/t/1624152.aspx
Notice this overload of Html.Partial():
Partial(HtmlHelper, String, Object, ViewDataDictionary)
http://msdn.microsoft.com/en-us/library/ee407417.aspx