I am relatively new to programming C# with ASP.NET MVC and I have a question. I am building some kind of cinema add show feature. I currently got the code where i can get all the CinemaShows with the right HallID based on a selected date (and send to the controller by a [Post]. Now I've put the information I need in a list of a ViewModel and I want to pass it along with the partial view so that when the POST method is called, the right info shows in a partial view. I will show the views and controllers code.
#using IVH7A5.WebUI.Models;
#using IVH7A5.Domain.Entities;
#model addShowViewModel
#{
ViewBag.Title = "addShow";
}
<div style="float:inherit">
#using (Html.BeginForm("getDateShows", "Show")) {
#Html.AntiForgeryToken()
<div class="form-horizontal">
<div class=" form-group">
<label class="control-label col-md-2">Datum</label>
<div class="col-md-10">
<input type="date" class="form-control" id="datum" name="datum" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button type="submit" class="btn btn-default">Toepassen</button>
</div>
</div>
</div>
}
</div>
<div>
#{Html.RenderPartial("_ShowsByCinema");}
</div>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Show</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<label class="control-label col-md-2">Zalen</label>
<div class="col-md-10">
<select class="form-control" name="cinemanumbers" id="cinemanumbers">
#foreach (Cinema cin in Model.Cinemas) {
<option value="#cin.cinemaNumber">#cin.cinemaNumber</option>
}
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2">Zalen</label>
<div class="col-md-10">
<select class="form-control" name="film" id="film">
#foreach (Movie movie in Model.Movies) {
<option value="#movie.MovieTitle">#movie.MovieTitle</option>
}
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2">3D</label>
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.Shows.ThreeD)
#Html.ValidationMessageFor(model => model.Shows.ThreeD, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2">Starttijd</label>
<div class="col-md-10">
#Html.EditorFor(model => model.Shows.StartTime, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Shows.StartTime, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
Note I do have some Dutch labels, as seen I use a different ViewModel that I want to pass to the partial view. My guess is that the RenderPartial() line needs some work.
My partial view:
#using IVH7A5.WebUI.Models;
#using IVH7A5.Domain.Entities
#model List<ShowsByCinema>
<div class="row">
<div class="col-lg-6 col-lg-offset-3 col-md-8 col-md-offset-2 col-sm-12 movie-film-times">
<h3>Zalen en tijden:</h3>
<div class="movie-by-day">
#foreach (ShowsByCinema x in Model) {
<div class="row">
<div class="col-xs-3 movie-day">
<strong>#x.cinemaNumber</strong>
</div>
<div class="col-xs-9">
#foreach (Show s in x.Shows) {
#s.StartTime.ToString("HH:mm") #:- #s.StartTime.AddMinutes(s.movie.MovieLength)
}
</div>
</div>
}
</div>
</div>
</div>
And, of course, the controller:
using IVH7A5.Domain.Abstract;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using IVH7A5.Domain.Entities;
using IVH7A5.WebUI.Models;
namespace IVH7A5.WebUI.Controllers {
public class ShowController : Controller {
private ICinemaRepository cinemaRepository;
private IMovieRepository movieRepository;
private IShowRepository showRepository;
public ShowController(ICinemaRepository cinemaRepo, IMovieRepository movieRepo, IShowRepository showRepo) {
cinemaRepository = cinemaRepo;
showRepository = showRepo;
movieRepository = movieRepo;
}
// GET: Show
public ActionResult Index() {
var model = new addShowViewModel();
model.Cinemas = cinemaRepository.cinemas;
model.Movies = movieRepository.Movies;
return View("addShow", model);
}
[HttpPost]
public ActionResult getDateShows(FormCollection form) {
List<ShowsByCinema> ShowsByCinemaList = new List<ShowsByCinema>();
DateTime date = Convert.ToDateTime(form["datum"]);
foreach (Cinema c in cinemaRepository.cinemas) {
ShowsByCinemaList.Add(new ShowsByCinema {
cinemaNumber = c.cinemaNumber,
Shows = showRepository.getshowsByCinemaAndDate(date, c.cinemaID)
});
}
return PartialView("_ShowsByDayPartial", ShowsByCinemaList);
}
}
}
So, to give a quick summary: I would like to know to render the partial view with the proper ViewModel when I call the POST method getDateShows. I am very new to programming in general and I would like to apologize if it contains code that is in contradiction with the code conventions. I hope someone can give me the solution to my problem. If any more information/code is required, feel free to ask.
Related
Im trying to load a MVC partial view in to a modal popup. The popup contains a drop down list which I am trying to populate on the ActionResult that loads when the view is loaded. The problem is the controller code isn't getting ran.
My code is as follows -
View:
<div id="modal_form_horizontal_addnote" class="modal fade">
<div class="modal-dialog modal-md">
<div class="modal-content">
<div class="modal-header bg-primary">
<button type="button" class="close" data-dismiss="modal">×</button>
<h5 class="modal-title">Add Note</h5>
</div>
#Html.Partial("AddNote", new IHD.Core.Models.CreateTicketNoteModel { TicketHeaderId = Model.Id })
</div>
</div>
The partial view:
#model IHD.Core.Models.CreateTicketNoteModel
#using (Html.BeginForm("AddNote", "Ticket", FormMethod.Post))
{
#Html.HiddenFor(model => model.TicketHeaderId)
#Html.AntiForgeryToken()
<div class="row">
<div class="col-md-12">
<div class="tab-content">
<div class="tab-pane active" id="highlighted-justified-tab1">
<div class="form-group">
#Html.LabelFor(model => model.WorkType, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-12">
#Html.DropDownListFor(model => model.WorkType, new SelectList(Model.WorkTypeOptions, "Key", "Value", Model.WorkType), new { #name = "select", #class = "form-control" })
#Html.ValidationMessageFor(model => model.WorkType, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
</div>
</div>
}
The controller:
public ActionResult AddNotePhase(int id = 0, int taskId = 0)
{
CreateTicketPhaseNoteModel note = new CreateTicketPhaseNoteModel();
note.TicketHeaderId = id;
// Populate the work type dropdown list
note.WorkTypeOptions.Add("", "-- Select a Work Type --");
note.WorkTypes = _workTypeService.GetAll().ToList();
foreach (var c in note.WorkTypes)
{
note.WorkTypeOptions.Add(c.Id.ToString(), c.Description);
}
//note.PhaseTask = taskId;
return PartialView(note);
}
You controller code isn't being hit because you are passing a model to the partial view and not calling the action. You need to use #{Html.RenderAction();} instead to call your action with the appropriate values.
I can add a create partial view within a modal bootstrap so that it can add value in the table with a edit view of the field value ?
My create partial view
#model MVCLayout.Models.Table2
<p>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="form-group">
#Html.Label("Cargo: ", new { style = "width:160px" })
#Html.TextBoxFor(model => model.ID, new { style = "width:200px" })
</div>
<br/>
<div class="form-group">
#Html.Label("Percentual: ", new { style = "width:160px" })
#Html.TextBoxFor(model => model.Name, new { style = "width:200px" })
</div>
<br/>
<div class="form-group">
#Html.Label("Serviço: ", new { style = "width:160px" })
#Html.TextBoxFor(model => model.Work, new { style = "width:200px" })
</div>
<br/>
<p>
<input type="submit" value="Save" />
</p>
}
</p>
My Edit View
<html>
<body>
#model MVCLayout.Models.Table1
#{
ViewBag.Title = "Edit";
}
<div id="signup">
<div class="rontainer">
<div class="header">
<div id="dock">
<br>
#using (Html.BeginForm("Edit", "AdmServicos", FormMethod.Post, new { #class = "form-inline" }))
{
#Html.AntiForgeryToken()
<fieldset>
<legend>Editar Servios</legend>
<br>
<div class="form-group">
#Html.Label("Código:", new { style = "width:160px" })
#Html.TextBoxFor(model => model.ID, new { style = "width:55px", #readonly = "readonly" })
<div class="form-group">
#Html.Label("Descrição: ", new { style = "width:160px" })
#Html.TextBoxFor(model => model.Descricao, new { style = "width:550px", #readonly = "readonly" })
</div>
</div>
<br />
<br /><br />
<p>
<input type="submit" value="Salvar" />
</p>
</fieldset>
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
#{
Html.RenderPartial("CreateTable2", Model.ID);
}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
}
</div>
</div>
</div>
</body>
</html>
Can I do this with a partial view or the best way to do this?
create a property of Table2 type in your Table1 Model like below :
public class Table1
{
public Table2 table2 {get; set;}
//other properties of Table1 Model
}
Now in your Edit View:
<div class="modal-body">
#{
Html.RenderPartial("CreateTable2", Model.table2);
}
</div>
Now in your Action of the Controller :
public ActionResult Edit(Table1 model)
{
var editPartialViewData = model.table2;
// Do whatever you want to do with this data
}
I know this question has been asked and answered a dozen of times but none of the solutions help me.
I have a following ViewModel which is consisted of ProductDetail data model and a list of Product_ProductCategoryAttribute data model.
public class ProductDetailViewModel
{
public ProductDetail ProductDetail { get; set; }
public List<Product_ProductCategoryAttribute> Product_ProductCategoryAttribute { get; set; }
}
On an action postback I receive an empty ViewModel.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "idProductDetail,idProductCategory,idProduct,Name,Description")] ProductDetailViewModel productDetailAll)
{
if (ModelState.IsValid)
{
ProductDetail productDetail = productDetailAll.ProductDetail;
db.Entry(productDetail).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(productDetailAll);
}
However, as I believe that the underlying problem is somewhere within the view I will add the view code snippet.
#using (Html.BeginForm("Edit", "ProductDetail", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.HiddenFor(model => model.ProductDetail.idProductDetail)
<div class="form-group">
#Html.LabelFor(model => model.ProductDetail.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.ProductDetail.Name, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ProductDetail.Description, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.ProductDetail.Description, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
#for (int i = 0; i < Model.Product_ProductCategoryAttribute.Count(); i++)
{
<div class="form-group">
<label class="control-label col-md-2">#Model.Product_ProductCategoryAttribute[i].ProductCategoryAttribute.Name</label>
<div class="col-md-5">
#Html.TextBoxFor(model => model.Product_ProductCategoryAttribute[i].Value, new { #class = "form-control" })
</div>
</div>
}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-sm btn-default" />
</div>
</div>
</div>
}
HTML generated from the view above is as follows (some parts are ommited for brevity):
<form action="/Administration/ProductDetail/Edit/4" method="post"><input name="__RequestVerificationToken" type="hidden" value="IS4fstTTjOD4d9FEzyM5yWlvO9xqlOq_AHFx_8_vC079F1iDvucf5wgRIgV4iXH-NGU-u-J8IHBiKT4ApvR3cSLbhw_AntbibEFsD68eUkc1" />
<input data-val="true" data-val-number="The field idProductDetail must be a number." data-val-required="The idProductDetail field is required." id="ProductDetail_idProductDetail" name="ProductDetail.idProductDetail" type="hidden" value="4" />
<div class="form-group">
<label class="control-label col-md-2" for="ProductDetail_Name">Name</label>
<div class="col-md-10">
<input htmlAttributes="{ class = form-control }" id="ProductDetail_Name" name="ProductDetail.Name" type="text" value="Čipka i hiljadu šara" />
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="ProductDetail_Description">Description</label>
<div class="col-md-10">
<input htmlAttributes="{ class = form-control }" id="ProductDetail_Description" name="ProductDetail.Description" type="text" value="Šipka i čipka" />
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2">Veličina</label>
<div class="col-md-5">
<input class="form-control" id="Product_ProductCategoryAttribute_0__Value" name="Product_ProductCategoryAttribute[0].Value" type="text" value="" />
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2">Širina</label>
<div class="col-md-5">
<input class="form-control" id="Product_ProductCategoryAttribute_1__Value" name="Product_ProductCategoryAttribute[1].Value" type="text" value="" />
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2">Pakiranje</label>
<div class="col-md-5">
<input class="form-control" id="Product_ProductCategoryAttribute_2__Value" name="Product_ProductCategoryAttribute[2].Value" type="text" value="" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-sm btn-default" />
</div>
</div>
</div>
I'm not sure if something is wrong with the naming convention but my bet would be on that.
The problem was in autogenerated controller Edit action which added couple of [Bind(Include="")] attributes which were wrong and which were preventing data to be posted to the server.
Correct snippet would look like this:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit (ProductDetailViewModel productDetailAll)
{
if (ModelState.IsValid)
{
ProductDetail productDetail = productDetailAll.ProductDetail;
db.Entry(productDetail).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(productDetailAll);
}
In this instance I have two pages, in the post method of the first I return the view/viewmodel of the second like so :
[HTTPPost]
public Task<ActionResult> Page1(Page1Model model)
{
var Page2Model = GrabDataMethod(model);
return View("Page2", Page2Model); //Point 1
}
[HTTPPost]
public Task<ActionResult> Page2(Page2Model model //Point 2)
{
var updatedModel= RunFiltersMethod(model)
return View(updatedModel);
}
Now, in this case Page2 renders properly from (Point 1) with all values passed in above from the GrabDataMethod. However, when I POST for Page2 the Page2Model I receive at (Point 2) has none of the original entries, e.g. everything not modified directly by Page2 itself is null or default (in fact it seems the model from the post method is a new model entirely). I've made a horrible workaround for the time being, but I need a proper fix, is there any reason that this would be happening?
Page2 View Code
#model Mvc2013.Models.Page2Model
#using (Html.BeginForm("Page2", "Controller"))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true)
<div class="row">
<div class="col-md-12">
#Html.Kendo().Chart(<!-- code removed, this is working -->)
</div>
</div>
<div class="row">
<div class="col-md-3">
<div class="col-md-8">
#Html.LabelFor(model => model.Prop1, new { #class = "control-label" })
</div>
<div class="col-md-4">
#Html.EditorFor(model => model.Prop1, new { #class = "control-label" })
#Html.ValidationMessageFor(model => model.Prop1)
</div>
</div>
<div class="col-md-3">
<div class="col-md-8">
#Html.LabelFor(model => model.Prop2, new { #class = "control-label" })
</div>
<div class="col-md-4">
#Html.EditorFor(model => model.Prop2, new { #class = "control-label"})
#Html.ValidationMessageFor(model => model.Prop2)
</div>
</div>
</div>
<!-- This carries on similarly for lots more attributes -->
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
Inside the Beginform you should add #Html.HiddenFor(model => model.Something) where the Something are the properties which you want back on the postback.
If you don't then the property values will be default values.
I have this model, Customer . When i get the information with an id, it works just fine.
Like ;
/Customer/Entity/5
#model ProgSpace.Models.Customer
#{
ViewBag.Title = Model.Name;
Layout = "~/Views/Shared/_MainLayout.cshtml";
}
#section bodypane
{
#using (Html.BeginForm("Entity", "Customer", FormMethod.Post, new { #enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="col-md-12">
<div class="col-md-1">
<label>Customer No:</label>
<h4># #(Model.ID) </h4>
</div>
<div class="clearfix"></div><br />
<div class="col-md-2">
<div class="col-md-12">
<div class="col-md-12 fileupload fileupload-exists" data-provides="fileupload">
<div class="fileupload-preview fileupload-exists thumbnail" style="width: 200px; height: 150px;">
<img src="#Model.Picture.Path" />
</div>
<div>
<span class="btn btn-default btn-file">
<span class="fileupload-new">Add Pic </span>
<span class="fileupload-exists">Change</span><input name="file" id="file" type="file">
</span>
Remove
</div>
</div>
</div>
</div>
<div class="col-md-10">
<div class="col-md-3">
<label>Name *</label>
#Html.TextBoxFor(model => model.Name, new { #class = "form-control"})
</div>
<div class="col-md-3">
<label>Company</label>
#Html.TextBoxFor(model => model.Contact.Company, new { #class = "form-control"})
</div>
<div class="col-md-3">
<label>Phone </label>
#Html.TextBoxFor(model => model.Contact.Phone, new { #class = "form-control" })
</div>
</div>
<div class="clearfix"><br /></div>
<p> </p>
<div class="col-md-12">
<div class="btn-group">
<button class="btn btn-danger btn-lg">Cancel</button>
<button type="submit" class="btn btn-success btn-lg">Send</button>
</div>
</div>
</div>
}
}
And in the controller i have these actions.
public ActionResult Entity(int id)
{
Customer cust= sis.Customers.Where(t => t.ID == id).FirstOrDefault();
return View(cust);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Entity(Customer cust, HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
/* Do something */
}
else
{
}
return View(cust);
}
When the verb is GET , it's fine. But when i post this form and when the second action (HttpPost action) kicks in , view throws an error..
Object reference not set to an instance of an object
which marks the Model.ID is null in the view.
<div class="col-md-1">
<label>Customer No:</label>
<h4># #(Model.ID) </h4> ---> THIS HERE THROWS NULL EXCEPTION
</div>
I've tried to add a HiddenFor for the Model.ID like
#Html.HiddenFor(t => t.ID)
but it didn't change anything.
How do i get back to the same view with the same context again ?