I have a page which has a list of Students. The partial view which renders a list is called "StudentManager". The partial view which I use in a modal to create a new student is called "NewStudent".
I have a couple of issues going on with this controller code. For some reason, after I press submit on the "NewStudent" partial view, every time afterwards that I refresh the page a new student is there without me going in and pressing submit... This is a problem.
Also, I have searched similar topics here on stack and I cannot seem to understand why return PartialView("StudentManager",db.Students.ToList()); will not automatically refresh my "StudentManager" view.
This code is supposed to give me a list in one partial view, and another partial view is supposed to let me create a new list item and then tell the list partial view to update.
Controller:
public ViewResult Index()
{
return View();
}
public ActionResult StudentManager()
{
return PartialView(db.Students.ToList());
}
public ActionResult NewStudent()
{
return PartialView();
}
//
// POST:
[HttpPost]
public ActionResult NewStudent(Student student)
{
if (ModelState.IsValid)
{
db.Students.Add(student);
db.SaveChanges();
return RedirectToAction("Index");
}
return PartialView();
}
Index.cshtml:
#Html.Action("StudentManager", "StudentController")
<div class="modal modal-wide fade" id="myModal4" role="dialog">
<div class="modal-dialog">
#Html.Action("NewStudent", "StudentController")
</div>
</div>
Here is the "NewStudent.cshtml" view:
#model GunneryTracker.Models.Student
<fieldset>
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<center>
<h4 class="modal-title">New Student</h4>
</center>
</div>
<div class="modal-body">
<div class="col-md-12">
<div class="clearfix"></div>
<div class="x_content">
<br />
<form class="form-horizontal form-label-left" >
<div class="form-group">
<div class="col-md-6 col-sm-6 col-xs-12">
<label class="control-label col-md-2 col-sm-2 col-xs-12" style="margin-right:10px">Course</label>
<div class="col-md-3 col-sm-3 col-xs-12">
#Html.DropDownList("CourseID", null, "-- Select Course --", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.CourseID, "", new { #class = "text-danger" })
</div>
<label class="control-label col-md-2 col-sm-2 col-xs-12" style="margin-right:10px">Location</label>
<div class="col-md-3 col-sm-3 col-xs-12">
#Html.DropDownList("LocationID", null, "-- Select Location--", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.LocationID, "", new { #class = "text-danger" })
</div>
</div>
<div class="editor-label">
#Html.LabelFor(model => model.FName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FName)
#Html.ValidationMessageFor(model => model.FName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.LName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LName)
#Html.ValidationMessageFor(model => model.LName)
</div>
</div>
<br />
<br />
<div class="form-group">
<center>
<p>
<input type="submit" value="Create" />
</p>
</center>
</div>
</form>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Save</button>
</div>
</div>
</fieldset>
Pardon the slouchy html... The prettyfication isnt completed...
Answer to 2nd question(if I understood what you meant):
It's not that smart as you expected.
After POST better to send back JSON result or simple null if don't use Ajax.
I would suggest you after POST do return RedirectToAction("Index");
Then page auto refresh students list.
Or do your POST via $.ajax and on success update student list using jquery or js
here is how I'm usually do it for simple "admin page" forms.
public ActionResult Teams()
{
var list = _data.GetTeams(true);
return View(list);
}
public ActionResult TeamCreate()
{
var model = _data.GetTeamCRUDViewModel();
return PartialView("_TeamCreate",model);
}
[HttpPost]
public ActionResult TeamCreate(TeamCRUDViewModel model)
{
_data.SaveTeam(model);
return RedirectToAction("Teams");
}
But on customer UI I would recommended to use $.ajax post.
Update:
Ok I see your issue
#model Student
<fieldset>
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">× </button>
<center>
<h4 class="modal-title">New Student</h4>
</center>
</div>
<div class="modal-body">
<div class="col-md-12">
<div class="clearfix"></div>
<div class="x_content">
<br />
#using (#Html.BeginForm("NewStudent", "Home", FormMethod.Post))
{
<div class="form-group">
<div class="col-md-6 col-sm-6 col-xs-12">
<label class="control-label col-md-2 col-sm-2 col-xs-12" style="margin-right: 10px">Course</label>
<div class="col-md-3 col-sm-3 col-xs-12">
#Html.DropDownList("CourseID", null, "-- Select Course --", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.CourseID, "", new { #class = "text-danger" })
</div>
<label class="control-label col-md-2 col-sm-2 col-xs-12" style="margin-right: 10px">Location</label>
<div class="col-md-3 col-sm-3 col-xs-12">
#Html.DropDownList("LocationID", null, "-- Select Location--", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.LocationID, "", new { #class = "text-danger" })
</div>
</div>
<div class="editor-label">
#Html.LabelFor(model => model.FName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FName)
#Html.ValidationMessageFor(model => model.FName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.LName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LName)
#Html.ValidationMessageFor(model => model.LName)
</div>
</div>
<br/>
<br/>
<div class="form-group">
<center>
<p>
<input type="submit" value="Create"/>
</p>
</center>
</div>
}
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Save</button>
</div>
</div>
Also change
#Html.Action("StudentManager", "StudentController") to #Html.Action("StudentManager", "Student")
like if should be name of controller
There's a fundamental misunderstanding here about how things work. A client makes a request to a server and the server returns a response. The client, then, generally does something with that response. In the case of a web browser, it clears the current view in the tab/window, parses the response and renders it into that tab/window. There's actually a lot more that goes on, but I'm trying to keep it simplistic.
However, AJAX (or specifically the XMLHttpRequest object in JavaScript) is what you would call a thin client. It's like a little web browser within your web browser, only without all the bells and whistles. All it does is submit requests and deliver the response to a callback. That callback is a JavaScript function whose job is to do something with the response. If the goal is to replace some portion of HTML on the page, the JavaScript code in the callback must do that. It does not happen automatically.
It's also important to realize that a "partial view" is only a thing server-side. Whether MVC is returning a partial view, a normal view, or even a view composed from various partial views is all inconsequential. What the server returns to the client is just an HTML document. In the case of the client being a web browser, it then parses that HTML document and builds what's called the Document Object Model, or DOM. It then uses the DOM to "render" the page as formatted images and text.
Likewise, all an AJAX request returns is an HTML document, which is itself really just a text document with a mime type of "text/html" that informs the client that it should be treated as HTML. As I said, it's the job of the AJAX callback to do something with this response from the server, but the point here is that you can't just say "replace that partial with this HTML", because the concept of partials doesn't exist client side. All you have is a object graph (the DOM), and you must select something from the DOM and then insert the HTML into that.
Related
first i create list of models in [HttpGet] action and return to view.
public ActionResult Setting()
{
var model = db.Settings.ToList();
return View(model);
}
them in view get list in view and show good.
but after edit the value of setting i want to pass list of object from view to controller don't work this.
#model List<TajerWebsite.Models.Setting>
<!-- Main content -->
<section class="content">
<div class="container-fluid">
<div class="row">
<!-- left column -->
<div class="col-md-6">
<!-- general form elements -->
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title">تنظیمات</h3>
</div>
<!-- /.card-header -->
<!-- form start -->
#using (Html.BeginForm("Setting","Admin", new { FormMethod.Post }))
{
#Html.AntiForgeryToken()
foreach (var item in Model)
{
<div class="card-body">
<div class="form-group">
#Html.HiddenFor(model => item.Id)
<label for="exampleInputPassword1">#item.Name</label>
#Html.EditorFor(model => item.Value, new { htmlAttributes = new { #class = "form-control"} })
#Html.ValidationMessageFor(model => item.Value, "", new { #class = "text-danger" })
</div>
</div>
}
<!-- /.card-body -->
<div class="card-footer">
<button type="submit" class="btn btn-primary">ذخیره</button>
</div>
}
</div>
</div>
</div>
</div>
</section>
and action is :
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Setting(IEnumerable<Models.Setting> settings)
{
db.Entry(settings);
db.SaveChanges();
return View(settings);
}
but settings is null!
You can't use #foreach loop in the view in order to pass list of object back to the controller, because that would generate input elements with same IDs and Names.
Instead, use standard for loop:
for(int i = 0; i < Model.Count; i++)
{
<div class="card-body">
<div class="form-group">
#Html.HiddenFor(m => m[i].Id)
<label for="exampleInputPassword1">#Model[i].Name</label>
#Html.EditorFor(m => m[i].Value,
new { htmlAttributes = new { #class = "form-control"} })
#Html.ValidationMessageFor(m => m[i].Value,
new { #class = "text-danger" })
</div>
</div>
}
I'm making Hotel management web app, and working on part where i need to add rooms ,problem is with dropdown menu, while adding knew code , I don't know why my dropdown menu stopped working ,it wokrked perfectly before but when added another part of code, dropdown just stoped wokring(when i click on it it wont drop), i removed code that i added before but a dropdown menu still doesent work.I added the part with the dropdown menu below
**index.cshtlm**
#model HotelManagement.ViewModel.RoomViewModel
{
ViewBag.Title = "Index";
}
<pre>
<div id="divAddRoom" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Room</h4>
</div>
<div class="modal-body">
<div class="container">
<div class="form-group ">
</pre>
#Html.LabelFor(model => model.RoomNumber)
#Html.TextBoxFor(model => model.RoomNumber, new { #class = "form-control", id = "txtRoomNumber" })
</div>
<div class="form-group">
#Html.LabelFor(model => model.RoomPrice)
#Html.TextBoxFor(model => model.RoomPrice, new { #class = "form-control", id = "txtRoomPrice" })
</div>
<div class="form-group ">
#Html.LabelFor(model => model.BookingStatusId)
#Html.DropDownListFor(model => model.BookingStatusId, #Model.ListOfBookingStatus, new { #class = "form-control", id = "ddBookingStatus" })
</div>
<div class="form-group ">
#Html.LabelFor(model => model.RoomTypeId)
#Html.DropDownListFor(model => model.RoomTypeId, #Model.ListOfRoomType, new { #class = "form-control", id = "ddRoomType" })
</div>
<div class="form-group ">
#Html.LabelFor(model => model.RoomCapacity)
#Html.TextBoxFor(model => model.RoomCapacity, new { #class = "form-control", id = "txtRoomCapacity" })
</div>
<div class="form-group ">
#Html.LabelFor(model => model.RoomDescription)
#Html.TextBoxFor(model => model.RoomDescription, new { #class = "form-control", id = "txtRoomDescription" })
</div>
<div class="form-group">
#Html.LabelFor(model => model.RoomImage)
<input id="UpLoadImage" type="file" class="form-control" name="roomImage" title="Load Image" onchange="DisplayImage(this)" />
<img id="imgRoom" height="200" width="280" style="border:solid" />
</div>
</div>
</div>
<div class="modal-footer">
<button id="btnSave" type="button" class="btn btn-success">Save</button>
<button type="button" data-dismiss="modal" class="btn btn-danger">Close</button>
</div>
</div>
</div>
Room_controler
enter code here
public ActionResult Index(){
RoomViewModel objRoomViewModel = new RoomViewModel();
objRoomViewModel.ListOfBookingStatus = (from obj in objHotelDbEntities.BookingStatus
select new SelectListItem()
{
Text = obj.BookingStatus,
Value = obj.BookingStatusId.ToString()
}).ToList();
objRoomViewModel.ListOfRoomType = (from obj in objHotelDbEntities.RoomTypes
select new SelectListItem()
{
Text = obj.RoomTypeName,
Value = obj.RoomTypeId.ToString()
}).ToList();
return View(objRoomViewModel);
}
image of the problem
I have two date values, that I need to validate. This validaton is compound: One date needs to be sooner than the other (think StartingDate and FinishDate).
How can I validate for this?
Based on this post, which seems to pose a similar situation, one recomendation is to use MVC Foolproof Validation. Is this still the best option? Is there other way to validate such task?
My code in the view, if it helps:
<div class="row">
<div class="col-md-3">
<div class="row">
<div class="col-md-5">
<span class="glyphicon glyphicon-calendar" aria-hidden="true"></span>
<span style="font-size:large;">Início </span>
</div>
<div class="col-md-7">
#Html.EditorFor(model => model.Inicio, new { htmlAttributes = new { #class = "form-control datetimepicker" } })
</div>
</div>
</div>
<div class="col-md-3">
<div class="row">
<div class="col-md-5">
<span class="glyphicon glyphicon-calendar" aria-hidden="true"></span>
<span style="font-size:large;">Fim </span>
</div>
<div class="col-md-7">
#Html.EditorFor(model => model.Fim, new { htmlAttributes = new { #class = "form-control datetimepicker" } })
</div>
</div>
</div>
</div>
<script>
<!--jQuery DateTimePicker-->
jQuery('.datetimepicker').datetimepicker({
format: 'd/m/Y H:i'
});
</script>
I don't see why a simple JS solution can't help here, so here it is:
HTML:
<p>Start Date: <input type="text" id="datepicker1"></p>
<p>End Date: <input type="text" id="datepicker2"></p>
<button id="TestCondition">
Click Me!
</button>
JS:
$(function() {
$("#datepicker1").datepicker();
});
$(function() {
$("#datepicker2").datepicker();
});
$("#TestCondition").click(function(){
alert($("#datepicker1").val());
alert($("#datepicker2").val());
if($("#datepicker2").val() < $("#datepicker1").val()){
alert("End Date must come after Start Date!");
}
});
Here is a fiddle for that: JSFiddle
Alternate Solution using Controller in MVC
Once you submit this page to the controller, you can do a check like so (C#):
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult NameOfAction(ViewModel nameOfViewModel)
{
if(nameofViewModel.FinishDate <= nameofViewModel.StartDate)
{
ModelState.AddModelError("FinishDate", "Finish Date needs to be after the Start Date!");
return View(nameOfViewModel);
}
}
Let me know if this helps, or if anything needs to be changed.
Based on BviLLe_Kid answer, which I accept, here's what I ended up doing:
if (ModelState.IsValid)
{
if (nameofViewModel.FinishDate <= nameofViewModel.StartDate)
{
ModelState.AddModelError(string.Empty, "Error message here");
return View(nameofViewModel);
}
else {
//code for when validation is OK
}
}
In the view:
<div style="color:red;">
#Html.ValidationSummary(true)
#Html.ValidationMessageFor(model => model.FinishDate)
</div>
I want to use label as used "Static Control" label on that page. However, although I use the same Bootstrap version, I cannot aligned my form controls like that (I want the label is right float, data fields is left float -side by side - and there is a ":" sign between them. Howwver, the result is as shown on the image below. Could you please have a look at my code and inform what is wrong?
The code on that page:
<div class="form-group">
<label class="col-md-3 control-label">Static Control</label>
<div class="col-md-9">
<p class="form-control-static"> email#example.com </p>
</div>
</div>
The code I use on my Razor page:
<div class="form-group">
#Html.LabelFor(m => m.Name, new { #class = "col-md-3 control-label" }):
<div class="col-md-9">
#Html.DisplayFor(m => m.Name, new { #class = "form-control-static" })
</div>
</div>
<br />
<div class="form-group">
#Html.LabelFor(m => m.Surname, new { #class = "col-md-3 control-label" }):
<div class="col-md-9">
#Html.DisplayFor(m => m.Surname, new { #class = "form-control-static" })
</div>
</div>
You have two elements which equal 100% width plus the colon, so it pushes the value down a line. You'll need to just code the label instead of using an HtmlHelper to add the colon. Change it to this:
<div class="form-group">
<label class="col-md-3 control-label">#Model.Name:</label>
<div class="col-md-9">
#Html.DisplayFor(m => m.Name, new { #class = "form-control-static" })
</div>
</div>
Here is the final solution fixed the problem. Thanks a lot for all of your helps...
<style>
.col-sm-3 .control-label {
float: right !important;
margin-top: 0 !important;
}
/*Add colon ( : ) to the end of labels */
.col-sm-3 > label:after {
content: " :";
}
</style>
<div class="form-group">
<div class="col-sm-3">
#Html.LabelFor(m => m.Name, new { #class = "control-label" })
</div>
<div class="col-sm-9">
#Html.DisplayFor(m => m.Name)
</div>
</div>
<br />
<div class="form-group">
<div class="col-sm-3">
#Html.LabelFor(m => m.Surname, new { #class = "control-label" })
</div>
<div class="col-sm-9">
#Html.DisplayFor(m => m.Surname)
</div>
</div>
<br />
I really don't know what I'm doing wrong. I want my textboxes with same size of my buttons below. I already tried change a lot in the cshtml but without success.
Below my cshtml file:
#model SomeModel.Models.LoginViewModel
<div class="row">
<div class="col-md-8 col-sm-12 col-xs-12">
<section id="loginForm">
#using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(m => m.UserName, new { #class = "col-md-2 control-label" })
<div class="col-md-12">
#Html.TextBoxFor(m => m.UserName, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.UserName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Password, new { #class = "col-md-2 control-label" })
<div class="col-md-12">
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Password)
</div>
</div>
<div class="form-group">
<div class="col-sm-12 col-xs-12">
<button type="submit" class="btn btn-success btn-block">Entrar</button>
</div>
</div>
<div class="form-group">
<div class="col-md-10 col-sm-12 col-xs-12 visible-sm visible-xs">
<button type="submit" class="btn btn-primary btn-block">Ainda Não Tenho Conta</button>
</div>
</div>
<div class="form-group">
<div class="col-md-10 col-sm-12 col-xs-12 visible-sm visible-xs">
<button type="submit" class="btn btn-info btn-block">Esqueci Meu Usuário Ou Senha</button>
</div>
</div>
<p>
#Html.ActionLink("Register", "Register") if you don't have a local account.
</p>
}
</section>
</div>
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
What am I doing wrong?
The default MVC5 template has a css rule in Site.css:
input, select, textarea { max-width: 280px; }
I usually remove this rule.
It causes problems with Bootstrap v3 input group where the input box does not extend to its container's width.