How to check if checkbox is checked - asp.net-mvc

I have question about accessing html.checkbox() in controller method.
In my view i have
<% foreach (var item in Model.PredmetTbl){ %>
<td>
<%:Html.CheckBox(item.Predmet) %>
<%:item.Predmet %>
</td>
<%} %>
Predemts are in DB and I want create new db records. How can i test if the checbox is checked or not ?
My controller code
[HttpPost]
public ActionResult PridajSaduPredmetov(int id, FormCollection data)
{
var zoznam = from predmet in ziakDB.PredmetTables select predmet;
ZoznamPredmetovTable predmety;
foreach (var item in zoznam)
{
if (HERE TESTING IF CHECKED)//IF Checked==true will add to db
{
predmety = new ZoznamPredmetovTable();
predmety.ZiakID = id;
predmety.PredmetID = item.PredmetID;
predmety.SkolskyRokID = IndexViewModel.GetSkolskyRokTeraz();
try
{
ziakDB.ZoznamPredmetovTables.InsertOnSubmit(predmety);
ziakDB.SubmitChanges();
}
catch { }
}
}
return RedirectToAction("DetailZiaka", "Administration", new { id = id });
}

(controlid).checked will return true/false

I did not make use of the html checkbox extension but I based my solution on this post:
How to handle checkboxes in ASP.NET MVC forms?
<% For Each item As x In Model.predmetTbl%>
<div><input type="checkbox" name="SelectedPredMet"
<% If Model.SelectedPredMet.Contains(item.Id) Then%>
checked="checked"
<% End If %>
value="<%: item.Id %>" /> <%: item.Predmet %></div>
<% Next%>

Related

MVC file uploader returns a null

I am basing my solution on this article;
http://dotnetslackers.com/articles/aspnet/ASP-NET-MVC-and-File-Uploads.aspx
However when I try to upload a picture I get a null instead of a filename.
My view looks like this;
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<SHP.Models.HrViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Edit Employee
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<fieldset>
<legend>Add details to the selected employee</legend>
<p>The photo you select for an employee will appear on MNet.</p>
<p>The qualifications you add for an employee will appear on their business cards when required.</p>
<% using (Html.BeginForm("EditEmployee", "HumanResources", FormMethod.Post,
new{enctype = "multipart/form-data"}))
{%>
<%: Html.AntiForgeryToken() %>
<%: Html.ValidationSummary(true) %>
<%: Html.EditorFor(model => model.EmployeeSelector) %>
<% if (Model.SelectedEmployee != null)
{ %>
<%: Html.HiddenFor(model => model.SelectedEmployee.EmployeeId) %>
<%: Html.HiddenFor(model => model.EmployeeName) %>
<table class="groupBorder" style="margin-top:15px; width:617px;">
<tbody>
<tr>
<th colspan="2">Add Details for <%: Model.EmployeeName %></th>
</tr>
<tr>
<td style="text-align: right;">
<%: Html.LabelFor(model => model.SelectedEmployee.Photo)%>
</td>
<td>
<input type="file" id="Picture" name="Picture" />
</td>
</tr>
<tr>
<td style="text-align: right;">
<%: Html.LabelFor(model => model.SelectedEmployee.Qualifications)%>
</td>
<td>
<%: Html.TextBoxFor(model => model.SelectedEmployee.Qualifications, new {style = "width:500px;"})%>
</td>
</tr>
<tr>
<td colspan="2" style="text-align: center;padding-top:20px;">
<input type="submit" value="Save" id="btnSubmit" /></td>
</tr>
</table>
<% } %>
<% } %>
</fieldset>
</asp:Content>
When you click on the Save button you go to this controller action;
[HttpPost]
[Authorize(Roles = "Administrator, HumanResources, ManagerAccounts, ManagerIT")]
[ValidateAntiForgeryToken]
[ValidateOnlyIncomingValues]
public ActionResult EditEmployee(HrViewModel hrvm)
{
if (ModelState.IsValid)
{
if (hrvm.SelectedEmployee == null
|| hrvm.EmployeeSelector.SearchTextId != hrvm.SelectedEmployee.EmployeeId)
{
return this.RedirectToAction(
"EditEmployee", new { employeeId = hrvm.EmployeeSelector.SearchTextId });
}
if (hrvm.SelectedEmployee.Picture.HasFile())
{
var destinationFolder = Server.MapPath("/Users");
var postedFile = hrvm.SelectedEmployee.Picture;
var fileName = Path.GetFileName(postedFile.FileName);
var path = Path.Combine(destinationFolder, fileName);
postedFile.SaveAs(path);
hrvm.SelectedEmployee.Photo = path;
}
var emp = Employee.GetEmployee(hrvm.SelectedEmployee.EmployeeId);
this.TryUpdateModel<IEmployeeHrBindable>(emp, "SelectedEmployee");
emp.Update();
this.TempData["Message"] = string.Format(
"At {0} Details updated for {1}", DateTime.Now.ToString("T"), hrvm.EmployeeName);
return this.View(hrvm);
}
return this.View(new HrViewModel());
}
So what am I doing wrong?
By default, MVC3 performs model binding based on the Name attribute of the input elements in your view.
To get file upload data, use the HttpPostedFileBase class as a parameter to your ActionResult and call the parameter 'file'.
[HttpPost]
[Authorize(Roles = "Administrator, HumanResources, ManagerAccounts, ManagerIT")]
[ValidateAntiForgeryToken]
[ValidateOnlyIncomingValues]
public ActionResult EditEmployee(HrViewModel hrvm, HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
if (hrvm.SelectedEmployee == null
|| hrvm.EmployeeSelector.SearchTextId != hrvm.SelectedEmployee.EmployeeId)
{
return this.RedirectToAction(
"EditEmployee", new { employeeId = hrvm.EmployeeSelector.SearchTextId });
}
if (file.ContentLength > 0)
{
hrvm.SelectedEmployee.Picture = file;
var destinationFolder = Server.MapPath("/Users");
var postedFile = hrvm.SelectedEmployee.Picture;
var fileName = Path.GetFileName(postedFile.FileName);
var path = Path.Combine(destinationFolder, fileName);
postedFile.SaveAs(path);
hrvm.SelectedEmployee.Photo = path;
}
var emp = Employee.GetEmployee(hrvm.SelectedEmployee.EmployeeId);
this.TryUpdateModel<IEmployeeHrBindable>(emp, "SelectedEmployee");
emp.Update();
this.TempData["Message"] = string.Format(
"At {0} Details updated for {1}", DateTime.Now.ToString("T"), hrvm.EmployeeName);
return this.View(hrvm);
}
return this.View(new HrViewModel());
}
(So if you could grab the image data using model binding, it would have been located at hrvm.Picture instead of hrvm.SelectedEmployee.Picture)
In your view use the following instead and the default model binding should work:
<%: Html.TextBoxFor(model => model.SelectedEmployee.Photo, new { type = "file" }) %>
That is assuming SelectedEmployee.Photo is of type HttpPostedFileBase.
The reason it isn't working at the moment is that the default model binder will be trying to find a property called Picture directly on the model, because that's the name of your file input. It won't find it, because Picture is a property of SelectedEmployee.
Changing it to what I've suggested above generates the correct id and name for the file input in the markup so when posted back has the correct path. This means the default model binder is then able to map between the form post value and the property.

How do I post two instances of the same property from a view to an action?

How can I send my data from form, two fields are the same: Station name, but they have different values. How send they via post method to controller. Asp.net mvc2
here what i try:
<% using (Html.BeginForm("ViewRes", "Shedule"))
{%>
<%= Html.ValidationSummary(true) %>
<fieldset>
<legend>Поиск по расписанию:</legend>
<ul>
<li>Из<%= Html.EditorFor(model => model.StationName) %></li>
<li>В<%= Html.EditorFor(model1 => model1.StationName) %></li>
<li>Дата отправления</li>
</ul>
<p>
<input type="submit" value="OK" />
</p>
</fieldset>
<% } %>
and such controller:
[HttpPost]
public ActionResult ViewRes(string a1, string b1)
{
DateTime dtm = Convert.ToDateTime("30.11.2011 0:00:00");
var res = (from d in db.RouteDetail
from m in db.RouteDetail
lalala
where (d.Station == a1
&&
m.Station == b1)
lalalal
}).ToList();
return View(res);
}
The way I would approach this is to refactor my model to encompass both of your existing inputs separately. That way each can be bound accordingly in the action.
public class RailwayRoute
{
public string StartStation { get; set; }
public string EndStation { get; set; }
}
View
<% using (Html.BeginForm("ViewRes", "Shedule"))
{%>
<%= Html.ValidationSummary(true) %>
<fieldset>
<legend>Поиск по расписанию:</legend>
<ul>
<li>Из<%= Html.EditorFor(model => model.StartStation) %></li>
<li>В<%= Html.EditorFor(model => model.EndStation) %></li>
<li>Дата отправления</li>
</ul>
<p>
<input type="submit" value="OK" />
</p>
</fieldset>
<% } %>
Controller/Action
[HttpPost]
public ActionResult ViewRes(string startStation, string endStation)
{
...
}
Expanding on tvanfosson's answer which pretty much sums up, I would try and decouple your data model from your view data. This is often done by using the MVVMC aproach where VM stands for view model. In your case you appear to be passing directly the data model to the view which is sometimes not the recommended approach.
So changing tvanfosson's RailwayRoute to a viewModel object I would ensure the controller action maps the data appropiately. Something like
[HttpPost]
public ActionResult ViewRes(RailwayRouteViewModel viewModel)
{
DateTime dtm = Convert.ToDateTime("30.11.2011 0:00:00");
var res = (from d in db.RouteDetail
from m in db.RouteDetail
lalala
where (d.Station == viewModel.StartStation
&&
m.Station == viewModel.EndStation)
lalalal
select new RailywayRouteViewModel()
{
StartStation = d.Station,
EndStation = m.Station
}
}).ToList();
return View(res);
}

How to bind list to a controller

How to bind a list to a controller?
Code in my controller, HTTPGET and HTTPPOST :
public ActionResult Client(string id)
{
List<Customer> Contacts = WebService.GetContactsOfClient(id);
return View(Contacts);
}
[HttpPost]
public ActionResult Client(List<Customer> custs)
{
// custs = null!!! Why??
return View();
}
Code in my view :
<% using (Html.BeginForm("Client", "Formulaire", FormMethod.Post, new { id = "form" })) { %>
<% foreach (var item in Model) { %>
<%:item.MiseAjour %><br />
<% } %>
<input type="submit" />
<% } %>
Thank you all...
If you want to get some values back in your POST action you need to POST them which is achieved using input fields:
<% using (Html.BeginForm() { %>
<%= Html.EditorForModel() %>
<input type="submit" value="OK" />
<% } %>
This outlines what you're trying to achieve.
Model Bind to a List<> when Posting JavaScript Data Object
If you have specific questions, post them
Your view is not rendering any html input elements which are required if you want the model binder to put your model back together on the post. See this answer here which shows binding to a collection and posting to back. Also check out this post for binding to a dynamic list.
Solution for me :
<legend>Contacts</legend>
<% for (int i = 0; i < Model.Contacts.Count; i++) { %>
<%: Html.EditorFor(model => model.Contacts[i],"Contact") %>
<% } %>
With this, I bind my list to controller!
Thank you all!!

How can we filter the records in a strongly typed partial view in ASP.NET MVC?

I have a strongly typed partial view that populates all the Records from Search table.
Now i have a textbox to enter name & a button to filter the records that can match a name.(Like Search page).
Can anybody provide code sample for this scenario?
My Main Page loads particular view based on the radiobutton selection(Search or Inquiry) as below using JQuery:
/* Loading the partial view based on radio button click... */
$(document).ready(function() {
$(':radio').click(function() {
if (this.value == '2') {
$('#ViewAllInquiries').load('/Home/Inquiry', function(html) { $('#ViewAllInquiries')[0].value = html; });
}
else {
$('#ViewAllInquiries').load('/Home/Search', function(html) { $('#ViewAllInquiries')[0].value = html; });
}
});
})
Here is my one of the Partial view ControllerCode:
[HttpGet]
public ActionResult Search()
{
var search = from s in entity.Search
select s; return PartialView(search);
}
Here is the User control Partial view(Search.ascx):
>" %>
<table >
<thead>
<tr>
<th align="left"> </th>
<th align="left"> TX_Id</th>
<th align="left">Name
<%= Html.TextBox("Name")%> <input type="submit" value="Filter" /></th>
<th align="left">Email Address</th>
</tr>
<% foreach (var item in Model)
{ %>
<%= Html.Encode(item.TX_Id) %>
"><%= Html.Encode(item.CustomerMaster.FullName()) %>
<%= Html.Encode(item.CustomerMaster.MS_Id) %>
<% } %>
Thanks for your time.
I do the same thing using an Ajax form. It's really easy. Here's the code I use:
Html:
<div>
<%
using (Ajax.BeginForm("Home", "Search", null,
new AjaxOptions { UpdateTargetId = "Output" },
new { id = "SearchForm" }))
{
%>
<!-- Form Fields -->
<input name="searchField" />
<input type="submit" value="Search" />
<%
}
%>
<div id="Output">
</div>
</div>
Then in the controller you just have:
public PartialViewResult Search(FormCollection form)
{
var model = YourSearchMethod(form["searchField"]);
return PartialView("Search", model);
}
The div with the id "Output" will be updated with your partial view result every time the submit button is clicked. In your case you have two different potential partial views, just submit the radio button value as part of your form and you can switch the output view from within the controller.
Why use FormCollection instead of parameters? I've had some difficult using named parameters with ajax forms, but you can try it and see how it works. It should look something like this instead:
public PartialViewResult Search(string searchField, bool inquiry)
{
if (inquiry)
{
var model = YourInquiryMethod(searchField);
return PartialView("Inquiry", model);
}
else
{
var model = YourSearchMethod(searchField);
return PartialView("Search", model);
}
}
I do the same on one of my sites but have implmented it a little diffently.
I have, in my View the following html;
<div class="EditProductContainer hidden"></div>
I also have the following jQuery;
function editBenefit(objThis) {
var id = $(objThis).parents('.Benefit').attr("id");
$.post("/Home/jQueryGetBenefit", { Id: id },
function(newHTML) {
$('.EditProductContainer').html(newHTML);
});
}
Then in my controller I have;
[AcceptVerbs(HttpVerbs.Post)]
public PartialViewResult jQueryGetBenefit(int Id)
{
Application application = Helpers.CacheHelper.Get();
Benefit thisBenefit = application.findBenefit(Id);
return PartialView("EditBenefit", thisBenefit);
}
I think this is doing what you want but I'm returning a rendered PartialView and replacing the contents of a containing div with the html generated by the partial view.
Hope this is of some help.

Saving a series of create forms with one submit button in ASP.Net MVC

To give some background on my issue:
I have 3 tables called Products, Packages, and PackageContents. I can go in my application and add products, and then I can create packages out of them. One of the steps of setting up a package is to create all the package contents. To do this, I've created a view that runs through all of the products and sets up a new package content for each - placing the packageID and productID in hidden fields. Then the user can select a dropdown for each one to indicate if the product is in the package, or not.
Here's my issue:
This renders a separate form for every product, each with it's own save button. I'd like to have one submit button that saves all of the new package contents at once. Can someone give me an example of how to write my POST method to loop over and save all new package contents and how I would make a button in my view that saves all of them at once?
My Model:
public class PackageContentViewModel
{
//Properties
public IEnumerable<Product> products { get; set; }
public Product product { get; set; }
public Package package { get; set; }
public PackageContent packageContent { get; set; }
//Constructor
public PackageContentViewModel(int id)
{
CustomerRepository customerRepository = new CustomerRepository();
package = customerRepository.GetPackage(id);
products = customerRepository.FindAllProducts().ToList();
foreach (var product in products)
{
PackageContent packageContent = new PackageContent();
{
packageContent.PackageID = id;
packageContent.ProductID = product.ProductID;
}
}
}
The Controller:
public ActionResult AddContents(int id)
{
Package package = customerRepository.GetPackage(id);
return View(new PackageContentViewModel(id) { });
}
The View:
<% foreach (var product in Model.products)
{ %>
<% using (Html.BeginForm())
{%>
<fieldset>
<legend><%= Html.Encode(product.ProductName) %></legend>
<%= Html.Hidden("PackageContentsID") %>
<%= Html.ValidationMessage("PackageContentsID", "*") %>
<%= Html.Hidden("PackageID", Model.package.PackageID) %>
<%= Html.ValidationMessage("PackageID", "*") %>
<%= Html.Hidden("ProductID", product.ProductID) %>
<%= Html.ValidationMessage("ProductID", "*") %>
<label for="InPackage">InPackage:</label>
<%= Html.TextBox("InPackage") %>
<%= Html.ValidationMessage("InPackage", "*") %>
<label for="Restricted">Restricted:</label>
<%= Html.TextBox("Restricted") %>
<%= Html.ValidationMessage("Restricted", "*") %>
<input type="submit" value="Create" />
</fieldset>
<% } %>
<% } %>
EDIT
I decided to post the code that ended up working for me, in case anyone else comes along and needs the same help:
My View:
<% int i = 0; using (Html.BeginForm("CreateContents", "Packages", new { id = Model.package.PackageID }))
{
foreach (var product in Model.products)
{
%>
<fieldset>
<legend><%= Html.Encode(product.ProductName)%></legend>
<%= Html.Hidden("PackageContents[" + i + "].PackageContentsID")%>
<%= Html.ValidationMessage("PackageContentsID", "*")%>
<%= Html.Hidden("PackageContents[" + i + "].PackageID", Model.package.PackageID)%>
<%= Html.ValidationMessage("PackageID", "*")%>
<%= Html.Hidden("PackageContents[" + i + "].ProductID", product.ProductID)%>
<%= Html.ValidationMessage("ProductID", "*")%>
<label for="InPackage">InPackage:</label>
<%= Html.TextBox("PackageContents[" + i + "].InPackage", "yes")%>
<%= Html.ValidationMessage("InPackage", "*")%>
<label for="Restricted">Restricted:</label>
<%= Html.TextBox("PackageContents[" + i + "].Restricted", "no")%>
<%= Html.ValidationMessage("Restricted", "*")%>
</fieldset>
<%
++i; } %>
<input type="submit" value="Add Contents" />
<% } %>
My Controller:
public RedirectToRouteResult CreateContents(int id, IList<PackageContent> PackageContents)
{
Package package = customerRepository.GetPackage(id);
foreach (var packageContent in PackageContents)
{
customerRepository.Add(packageContent);
customerRepository.Save();
}
return RedirectToAction("SetPrice", new { id = package.PackageID });
}
Here you can read about binding to a list: Model binding to a list
This article is old, in newer MVC version you don't have to define <input type="hidden" name="products.Index" value="0" />, but the rest is valid.
EDIT
Answer to comment:
If only thing that you do is select if product is in the package or not, you can use MultiSelectList.
If you want to specify quantity or other attibutes, you can write:
<% int i = 0; using (Html.BeginForm()) {%>
<% foreach (var product in Model.products) { %>
<label for="Restricted"><%= product.Name %></label>
<%= Html.Hidden("products[" + i + "].ProductId",product.id) %>
<%= Html.TextBox("products[" + i + "].Quantity",0) %>
<br/>
<% ++i; } %>
<% } %>
Post action:
[HttpPost]
public ActionResult Edit(IList<PackageContent> products)
where PackageContent is
class PackageContent
{
int ProductId{get;set;}
int Quantity{get;set;}
}

Resources