how to Call controller when click the button? - c#

I want to call a controller when click the button in view.How can I do it in MVC?.
This is my first controller.
public ActionResult DetailForm()
{
graduandModel model = new graduandModel();
var ceremonyList = _ceremonyService.GetAllCeremonyByDate(DateTime.Now);
if (ceremonyList.Count == 0)
{
return Content("No ceremony can be loaded");
}
else
{
foreach (var c in ceremonyList)
{
model.AvailableCeremony.Add(new SelectListItem() {
Text = "Ceremony at " + c.ceremony_date.ToString(),
Value = c.ceremony_id.ToString() });
}
return View(model);
}
}
This is my view.
#{
Layout = "~/Views/Shared/_ColumnsThree.cshtml";
}
#model graduandModel
#using Nop.Web.Models.Hire;
#using Nop.Web.Framework;
#using Telerik.Web.Mvc.UI;
#using System.Linq;
<table>
<tr>
<td>
#Html.LabelFor(model => model.ceremony_id)
</td>
<td>
#Html.DropDownListFor(model => model.ceremony_id, Model.AvailableCeremony)
</td>
</tr>
<tr>
<td>
#Html.LabelFor(model => model.first_name):
</td>
<td>
#Html.EditorFor(model => model.first_name)
</td>
</tr>
<tr>
<td>
#Html.LabelFor(model => model.middle_name):
</td>
<td>
#Html.EditorFor(model => model.middle_name)
</td>
</tr>
<tr>
<td>
#Html.LabelFor(model => model.last_name):
</td>
<td >
#Html.EditorFor(model => model.last_name)
</td>
</tr>
<tr>
<td>
#Html.LabelFor(model => model.student_id):
</td>
<td>
#Html.EditorFor(model => model.student_id)
</td>
</tr>
<tr>
<td colspan="2" class="buttons">
<input type="submit" id="btnsearchgraduand" name="btnsearch"
class="searchbutton" value="#T("Search")" />
</td>
</tr>
</table>
Then When I click the search button I want to check the input data.
Should I write new controller like this
public ActionResult CheckDegreeDetails()
{
graduandModel model = new graduandModel();
var degreeList = _graduandService.GetGraduandByStudent(
model.ceremony_id, model.first_name,
model.middle_name, model.last_name);
return View(model);
}
Or...
I don't know how to call controller when click the button...

You want to wrap your user input fields and the submit button in a form. You can use an html helper that will also let you specify the controller action to call.
So modify your view:
...
#model graduandModel
#using Nop.Web.Models.Hire;
#using Nop.Web.Framework;
#using Telerik.Web.Mvc.UI;
#using System.Linq;
#using(Html.BeginForm("DetailForm", "ControllerName", FormMethod.Post, new {enctype="multipart/form-data"})
{
<table >
<tr>
<td >
#Html.LabelFor(model => model.ceremony_id)
</td>
...
//code omitted for brevity
...
<input type="submit" id="btnsearchgraduand" name="btnsearch" class="searchbutton" value="#T("Search")" />
})
Then in your controller you need to add the method to 'catch' this form. You're already using a strongly typed view so capturing the data is easy
[HttpPost]
public ActionResult DetailForm (graduandModel model)
{
//do what you need to do with the data here
//the model passed into this method's parameter should
//contain all the data from the editor templates in the view
}

The way you have your button, it won't make the request.
You can use jQuery/javascript.
HTML:
Javascript:
function callController()
{
$.get("YourController/Action",data, callBackMethod);
}
Or you can wrap your input, buttons etc... using #using(Html.BeginForm(..))

Related

Change DevExpress MVC ComboBox selected value based on another combobox value

My code is below. I have 4 comboboxes, all in separate partial views, and I want to change the selected value of the county combobox when I select the judge combobox. The judge combobox has the county in the selection so you have the name or I can look up the county based on the judgeid How do I do that?
...
#model TestCascadeCombobox.Models.CCmaster
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<table>
<tr>
<td>
<div style="padding:5px">
#Html.Label("County", "County")
</div>
</td>
<td>
<div style="padding:5px">
#Html.Partial("CountyPartial", Model)
</div>
</td>
<td>
<div style="padding:5px">
#Html.Label("Judge", "Judge")
</div>
</td>
<td>
<div style="padding:5px">
#Html.Partial("JudgePartial", Model)
</div>
</td>
</tr>
<tr>
<td>
<div style="padding:5px">
#Html.Label("Year", "Year")
</div>
</td>
<td>
<div style="padding:5px">
#Html.Partial("YearPartial", Model)
</div>
</td>
<td>
<div style="padding:5px">
#Html.Label("Month", "Month")
</div>
</td>
<td>
<div style="padding:5px">
#Html.Partial("MonthPartial", Model)
</div>
</td>
</tr>
</table>
}
Next is the Partial View for the Judge
#model TestCascadeCombobox.Models.CCmaster
#Html.DevExpress().ComboBox(settings =>
{
settings.Name = "Judge";
//settings.CallbackRouteValues = new { Controller = "CircuitCaseloads", Action = "JudgePartial"};
settings.Properties.ValueType = typeof(int);
settings.Properties.TextField = "FullName";
settings.Properties.ValueField = "JudgeID";
settings.Properties.ClientSideEvents.SelectedIndexChanged = "function(s,e) { County.PerformCallback(); Month.PerformCallback(); }";
}).BindList(Model.judges).Bind(Model.judge).GetHtml()
The main idea it to handle the client-side SelectedIndexChanged event of the (judge) ComboBox and update the related (county) ComboBox via a callback. Check out the related MVC ComboBox Extension - How to implement cascaded combo boxes guide to find all the necessary implementation details.
Here is what I did to fix my problem.
function CountyComboBox_EndCallBack(s, e) {
s.SetValue(County.cpcountyid);
}
settings.Properties.ClientSideEvents.EndCallback = "CountyComboBox_EndCallBack";
settings.CustomJSProperties = (s, e) =>
{
e.Properties["cpcountyid"] = ViewData["countyid"];
};

Failing to pass data from view to the Action by Html.BeginForm()

I am very new at asp.net mvc, so the reason behind my failure might be something basic as well, but I can't seem to find it after nearly a days work now.
What I am trying to do is to get the edited Model from the Index view and pass it to a second action which does not have view and returns return RedirectToAction("Index") in the related controller. In OrdersItemsController my Action is as the following:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult MarkedShipped(IEnumerable<orders_items> orderItems)
{
if (ModelState.IsValid)
{
foreach (var item in orderItems)
{
unitOfWork.GenericRepository<orders_items>().Update(item);
}
}
return RedirectToAction("Index");
}
And in the Index.cshtml which is in OrdersItems folder in the Views, what I did is as following:
#model IEnumerable<Project.DataAccess.orders_items>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm("MarkedShipped", "OrdersItems", new { orderItems = Model }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.quantity)
</th>
<th>
#Html.DisplayNameFor(model => model.itemprice)
</th>
<th>
#Html.DisplayNameFor(model => model.trackingnumber)
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.quantity)
</td>
<td>
#Html.DisplayFor(modelItem => item.itemprice)
</td>
<td>
#Html.EditorFor(modelItem => item.trackingnumber)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.itemid })
</td>
</tr>
}
</table>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="MarkShipped" class="btn btn-default" />
</div>
</div>
}
My problem is, I am not able to get the Model from the view with orderItems parameter, I am not sure if this is the right "syntax" for what I am trying to accomplish; but what I get for orderItems when the action is called is a List of orders_items with Count = 0 not a null value.
I have also checked if there is an application level exception, but got no exception from Application_Error in Global.asax
I am stuck for a day now so If anyone can point me a direction on how to pass the Model (or "the edited data") to the action for me to update the db, I would be very grateful. Thanks.
Firstly you cannot add a model which is a collection (or a model which contains a property which is a complex object or collection) to a forms route parameters. Internally the helper calls the .ToString() method and if you inspect the html generated for your form tag you will see something like
<form action=OrdersItems/MarkedShipped?orderItems=System.Collection.Generic.......
and binding will fail since you collection cannot be bound to a string. Even if it did work, it would be rather pointless because it would just post back the original values of the model.
Next, you cannot use a foreach loop to generate form controls. Again if you inspect the html your generating you will see that the EditorFor() method is generating inputs with duplicate id attributes (invalid html) and duplicate name attributes which do not have the necessary indexers to bind to a collection when you post. You need to use either a for loop of a custom EditorTemplate for typeof orders_items
Using a for loop means that your model must implement IList<T> and the view needs to be
#model IList<Hochanda.CraftsHobbiesAndArts.DataAccess.orders_items>
#using (Html.BeginForm()) // only necessary to add the controller and action if they differ from the GET method
{
....
#for(int i = 0; i < Model.Count; i++)
{
#Html.DisplayFor(m => m[i].quantity)
....
#Html.EditorFor(m => m[i].trackingnumber)
}
....
}
Using an EditorTemplate, create a partial in /Views/Shared/EditorTemplates/orders_items.cshtml (note the name of the file must match the name of the class)
#model Hochanda.CraftsHobbiesAndArts.DataAccess.orders_items
<tr>
<td>#Html.DisplayFor(m => m.quantity)</td>
....
<td>#Html.EditorFor(m => m.trackingnumber)</td>
....
</tr>
and then in the main view (you can use IEnumerable<T>)
#model IEnumerable<Hochanda.CraftsHobbiesAndArts.DataAccess.orders_items>
#using (Html.BeginForm())
{
<table class="table">
<thead>
....
<thead>
<tbody>
#Html.EditorFor(m => m)
</tbody>
</table>
....
}
The EditorFor() method accepts IEnumerable<T> and will generate one row for each item in you collection based on the html in the EditorTemplate
In both cases, it you inspect the html you will now see the correct name attributes necessary for you model to bind when you post
<input type="text" name="[0].trackingnumber" ... />
<input type="text" name="[1].trackingnumber" ... />
<input type="text" name="[3].trackingnumber" ... />
Try For instead of foreach here.
#for (int i = 0; i < Model.Count; i++)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.quantity)
</td>
<td>
#Html.DisplayFor(modelItem => item.itemprice)
</td>
<td>
#Html.EditorFor(modelItem => item.trackingnumber)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.itemid })
</td>
</tr>
}
Check this :- http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/
You can do the following
for (int i = 0; i < #ViewBag.Persons; i++)
{
<li>
<table>
<tr>
<td>
#Html.LabelFor(m => m.Fullname,new { #id = "FullnameLabel" + #i })
</td>
<td>
#Html.TextBoxFor(m => m.Fullname, new { #id = "Fullname" + #i })
</td>
</tr>
In this way each html element gets its own unique id and its possible to retrieve the information back from them individually. You can use for or Foreach. Just make sure that your razor iterator is functioning. You can view the element ids in the source to see if it is working.

MVC viewmodel is null on post (editing multiple rows)

I'm new to ASP.NET MVC and have been searching for a solution to this problem for hours. I'm trying to create a site where admins can go in and approve registration user requests and also assign them to a user group. I'm getting data from multiple tables so I created a viewmodel.
I finally have the GET Edit controller working to display the data, but can't figure out how the POST Edit should work. When I was debugging, I realized that the viewmodel I was trying to return had only null values.
I'm not sure if there are many things wrong with this code or just one. On postback, I need to update some values in the Access table. If you need more information from me, just let me know. Thanks!
ViewModel:
using System.Collections.Generic;
using AccessRequests.Models;
using System.ComponentModel.DataAnnotations;
namespace AccessRequests.ViewModels
{
public class UserAccessData
{
public IEnumerable<User> Users { get; set; }
public IEnumerable<Access> Accesses { get; set; }
public IEnumerable<UserGroup> UserGroups { get; set; }
}
}
Controller:
// GET: Accesses/Edit/5
public ActionResult Edit(string brand, string group)
{
var viewModel = new UserAccessData();
viewModel.Users = db.Users
.Include(i => i.Accesses)
.OrderBy(i => i.UserName);
viewModel.UserGroups = db.UserGroups
.Where(i => i.Groups.Contains(group));
if (brand != null)
{
viewModel.Accesses = db.Accesses
.Include(x => x.User)
.Where(x => x.Brand.ToUpper() == brand);
}
return View(viewModel);
}
// POST: Accesses/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Access access, UserAccessData editaccess)
{
//code here
}
View:
#model AccessRequests.ViewModels.UserAccessData
#{
ViewBag.Title = "Edit";
}
<h2>Edit Access</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<table class="table">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
<th>Company</th>
<th>Role</th>
<th>Region</th>
<th>User Group</th>
<th>Approve</th>
<th>Deny Reason</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Accesses)
{
#Html.HiddenFor(modelItem => item.UserName)
<tr>
<td>
#Html.DisplayFor(modelItem => item.User.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.User.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.User.Email)
</td>
<td>
#Html.DisplayFor(modelItem => item.User.Company)
</td>
<td>
#Html.DisplayFor(modelItem => item.User.Role)
</td>
<td>
#Html.DisplayFor(modelItem => item.User.Region)
</td>
<td>
#Html.DropDownListFor(m => m.UserGroups, new SelectList(Model.UserGroups, "Groups", "GroupDescription"), "Please select a User Group")
</td>
<td>
#Html.DropDownListFor(modelItem => item.Approved, new SelectList(
new List<Object>{
new { value = 0 , text = "" },
new { value = "YES" , text = "YES" },
new { value = "NO" , text = "NO"}
},"value","text", 2))
</td>
<td>
#Html.EditorFor(modelItem => item.DenyReason, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(modelItem => item.DenyReason, "", new { #class = "text-danger" })
</td>
</tr>
}
</tbody>
</table>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
In order to post to a collection property, your field names need to be in the form of something like: Accesses[0].Approved, Accesses[1].Approved, etc. In order to achieve that, you need to use a for loop rather than foreach. You'll also need to change your property's type from IEnumerable<Access> to List<Access>.
#for (var i = 0; i < Model.Accesses.Count(); i++)
{
...
#Html.DropDownListFor(m => Model.Accesses[i].Approved, ...)
}
Also, bear in mind that only those properties which have actual HTML fields that participate in the the post will have values in your post action. Everything else will either be null or whatever default value the property may have. If you save an entity with properties that have been nulled out because they weren't posted, you will overwrite those properties in your database. You need to take care to either make sure all the necessary data comes through in the post or that you repopulate said data from the the database before attempting to save anything.

select all tr of a table and send it to the controller using checkbox , in MVC 4

I want to use the Check box for selecting multiple users and sending the result to my controller.
At first I was only sending the number of mobile users to the controller but it became necessary to send more than the number, I need number and name user, my controller and my view are as follows:
Would somehow send the number and name for example?
#using (Html.BeginForm("Enviar", "Home")) {
<table id="myTable">
<thead>
<tr>
<th>
<input type="checkbox" />
</th>
<th>#Html.DisplayName("Nome")</th>
<th>#Html.DisplayName("CANCELADO")</th>
<th>#Html.DisplayName("Numero")</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model) {
<tr>
<td>
<input type="checkbox" name="CELULAR" value="#item.CELULAR" />
</td>
<td name="Nome">#Html.DisplayFor(modelItem => item.NOME)</td>
<td name="Email">#Html.DisplayFor(modelItem => item.CANCELADO)</td>
<td name="Celular" value="#item.CELULAR">#Html.DisplayFor(modelItem => item.CELULAR)</td>
</tr>
}
</tbody>
</table>
<input type="submit" value="Selecionar"/>
}
The controller that receives:
[HttpPost]
public ActionResult Enviar(String[] celular) {
.....
return View();
}
When posting collections, you must index them correctly. Therfore, you must use a for loop instead of a foreach.
Also, why does your HttpPost take a String[] and not your Model? First change that to be your model type.
Assuming your model is: #model List<YourType>
Change your HttpPost to take that:
[HttpPost]
public ActionResult Enviar(List<YourType> model) {
.....
return View();
}
Now we'll rewrite your foreach into a for and use the CheckBoxFor helper. Also, add HiddenFor fields for any properties you want to see on post:
#for (int i = 0; i < Model.Count; i++)
{
<tr>
<td>
#Html.CheckBoxFor(m => m[i].CELULAR)
</td>
<td name="Nome">
#Html.HiddenFor(m => m[i].NOME)
#Html.DisplayFor(m => m[i].NOME)
</td>
<td name="Email">
#Html.HiddenFor(m => m[i].CANCELADO)
#Html.DisplayFor(m => m[i].CANCELADO)
</td>
<td name="Celular" value="#m[i].CELULAR">
#Html.DisplayFor(m => m[i].CELULAR)
</td>
</tr>
}

Why httpPost model always null?

I have get and post controller.
But by httpPost comtroller passing model parameter values are null.
Why my httpPost model parameter values always null ??
[HttpGet]
public ActionResult HireItem()
{
var HireItemListModel = new HireItemModel();
HireItemListModel = new HireItemModel()
{
first_name = Session["first_name"].ToString(),
middle_name = Session["middle_name"].ToString(),
last_name = Session["last_name"].ToString(),
ceremony_date = Session["ceremony_date"].ToString(),
};
var product = _productService.GetAllHireProducts();
if (product.Count != 0)
{
foreach (var proValue in product)
{
var productVarSeparateList = _productService.GetHireProductVariantsByProductIds(proValue.Id, false);
foreach (var HireProSep in productVarSeparateList)
{
var productVarSeparateModel = new HireItemModel.HireItemSeparatetModel()
{
pname = HireProSep.Name,
price =HireProSep.Price,
pId=HireProSep.Id,
};
HireItemListModel.HireItemSeparatetlist.Add(productVarSeparateModel);
}
var productVarSetList = _productService.GetHireProductVariantsByProductIds(proValue.Id, true);
foreach (var HireProset in productVarSetList)
{
var productVarListset = new HireItemModel.HireItemSetModel()
{
pname = HireProset.Name,
price = HireProset.Price,
pId = HireProset.Id,
};
HireItemListModel.HireItemSetList.Add(productVarListset);
}
}
}
return View(HireItemListModel);
}
This controller HireItemModel model parameter values are null. WHY??
[HttpPost,ActionName("HireItem")]
public ActionResult HireItem(string submitB, FormCollection formCollection, HireItemModel HireItemListModel)
{
var graduandList = _graduandService.GetGraduandBynameCeremony(HireItemListModel.ceremony_id, HireItemListModel.first_name, HireItemListModel.middle_name, HireItemListModel.last_name);
foreach (var graduand in graduandList)
{
graduand.height = HireItemListModel.height;
graduand.head_circumference = HireItemListModel.head_circumferenc;
_graduandService.Updategraduand(graduand);
}
this is my view.
#model HireItemModel
#using (Html.BeginForm())
{
<table >
<tr>
<td >
Ceremony :
</td>
<td>
Ceremony at #Model.ceremony_date
</td>
</tr>
<tr>
<td >
Name :
</td>
<td >
#Model.first_name #Model.middle_name #Model.last_name
</td>
</tr>
</table>
<div id="HItemType_1">
#Html.CheckBox("HItemType")
#*<input type="checkbox" name="test" value="test" id="HItemType" />*#
<label> Academic Dress Set</label>
</div>
<div id="HsetItem">
#Html.Partial("_LoadHireSetItem", #Model.HireItemSetList)
</div>
<div id="HseparateItem">
#Html.Partial("_LoadHireSeparateItem", #Model.HireItemSeparatetlist)
</div>
<table >
<tr>
<td colspan="2">
Please tell us your measurement:
</td>
</tr>
<tr>
<td >
Height (in cm):
</td>
<td>
#Html.EditorFor(model => model.height)
</td>
</tr>
<tr>
<td >
Head circumference (in cm):
</td>
<td >
#Html.EditorFor(model => model.head_circumferenc)
</td>
</tr>
</table>
<div>
<input class="productlistaddtocartbutton" type="submit" value="Add to cart" name="submitB" id="btnaddtocart"/>
</div>
}
thanks.
Make sure inside your view you have input fields for all values that you intend to use in your POST action. For example if you want to use the ceremony_id, first_name, middle_name, and last_name properties you need to include them:
#Html.HiddenFor(model => model.ceremony_id)
#Html.HiddenFor(model => model.first_name)
#Html.HiddenFor(model => model.middle_name)
#Html.HiddenFor(model => model.last_name)
You could use hidden fields if the user is not supposed to modify their values but you could also have used text fields depending on your requirements.

Categories