How to keep click event dynamically created buttons in mvc - c#

i have retrive name of buttons from database those button when i click a
button i need to show the some report.now i have everything is done.i
need to know how keep unique id for those buttons and how they worked
when i click button i need to show report in a separate page...
[HttpGet]
public ActionResult Estate()
{
return View("Estate", new EstateFunc().Estates());
}
[HttpPost]
public ActionResult Estate(int id=0)
{
if(id>0)
{
}
return View();
}

With MVC
View:
#foreach (var item in Model)
{
<tr>
<td>#item.Something...</td>
<td>#item.AnotherThing</td>
<td>
</td>
</tr>
}
This Razor code will generate as many button as the count of the collection items in your model. Every item in the collection should have unique ID and as you see we put this ID as parameter. So when the user clicks on any of the buttons, the unique ID will tell us which button was clicked (and to which item we should refer to)
Controller:
public ActionResult MyAction(int id = 0)
{
var model = ReportViewModel(id);
return ReportView(model);
}
private ReportViewModel(int id)
{
// Get Report from Database Where Id = id
// Populate ViewModel from the database data
// Return reportViewModel;
}
EDIT (adding example based on your code)
#foreach (var item in Model)
{
<div class="floated">
<a href="#Url.Action("MyAction", "MyController", new { Id = item.Id })"
class="Estates_button">#item.EstateName</a>
</div>
}

Related

How can we get the Id of an item inside the controller?

So basically as the title said, currently working on a MVC5, how can I get the Id of the list of Items that I have in view of the controller? By a button click, I'm calling an action which doesn't have a view but requires the Id of the item, which is resulting in a NULL.
I read this article but they don't seem to work for me:
How to get the current user in ASP.NET MVC
public ActionResult GetItem(int Id)
{
Item item = new Repository().GetId(Id);
..
}
Okay, so after a discussion on the requirement, the following changes were required to be made on the View:
<div class="col-lg-4">
<a href="#Url.Action("GetItem", "Upload", new { id = Model.id}"">
</a>
<P>#p.Path</P>
</div>
And the Controller:
public ActionResult GetItem(int id)
The URL for each item would be generated uniquely based on the Model.id

How to pass view data to typed controller object?

I'm moving from WPF development to Asp MVC and have started doing an Asp MVC app. So far I've set up my:
model
controller
and
view(with the relevant fields.)
The next step involves sending the data entered in my form to the controller on the Submit button click.
I know in WPF I can bind the control properties to a property in the viewmodel, also there would be a click event on the button which I don't see in MVC.
This is my pseudo understanding of how to do that in MVC but correct me if I' wrong (Model is of type Case):
1.Set button click event to send form data to controller.
2.Pass data into controller constructor and assign to typed Case object.
Question:
How can you pass view values on button submit to a typed object in a controller?
Code:
View -
<form action="" method="post">
<div class="form-horizontal">
<div class="col-lg-6">
<!-- SELECT STATUS STATIC-->
<div class="form-group">
<label class="col-md-3 control-label" for="Current Status">Status</label>
<div class="col-md-8">
<select id="Status" name="Status" onchange="" class=" form-control">
<option value="Down">Down</option>
<option value="Up">Up</option>
</select>
</div>
</div>
<!-- SELECT APP STATIC-->
<div class="form-group">
<label class="col-md-3 control-label" for="App">App</label>
<div class="col-md-8" >
<select id="App" name="App" onchange="" class=" form-control">
<option value="SAP">SAP</option>
<option value="JAP">JAP</option>
</select>
</div>
</div>
<asp:Button id="b1" Text="Submit" runat="server" />
</div>
</div>
</form> <!--
Controller -
public class CaseController : Controller
{
public ActionResult Index()
{
return View();
}
}
Model -
Public class Case
{
public string Status { get; set; }
public string App { get; set; }
}
I hope that I understand your scenario well? You have a form with two drop down lists and a submit button? When you click the submit button you want to extract the selected values? This is how I understand it and this is how I will try to explain my answer with examples.
I would suggest that you bind your view/page to a view model. A view model is a kind of model that will represent your data in the view, whether it be textboxes, drop down lists, textareas, radio buttons, checkboxes, etc. It can also display static text on your view. I wrote a detailed answer as to what a view model is, if you have the time please go and read it:
What is ViewModel in MVC?
Go and create your view model. It will contain two lists that will represent your two drop down lists. Each list has an id associated with it that will contain the value of the selected drop down list item:
public class CaseViewModel
{
public int StatusId { get; set; }
public List<Status> Statuses { get; set; }
public int AppId { get; set; }
public List<App> Apps { get; set; }
}
Your domain models, namely Status and App, for the above mentioned lists:
public class Status
{
public int Id { get; set; }
public string Name { get; set; }
}
public class App
{
public int Id { get; set; }
public string Name { get; set; }
}
Now that you have this setup your next step is to populate these lists in your controller's action method. Ideally you would populate it with values from a database, but in your case I guess it is ok to hard code these values:
public ActionResult Index()
{
CaseViewModel model = new CaseViewModel();
model.Statuses = new List<Status>();
model.Statuses.Add(new Status { Id = 1, Name = "Down" });
model.Statuses.Add(new Status { Id = 2, Name = "Up" });
model.Apps = new List<App>();
model.Apps.Add(new App { Id = 1, Name = "SAP" });
model.Apps.Add(new App { Id = 2, Name = "JAP" });
return View(model);
}
As soon as you have populated your two lists, you pass the view model directly to the view. The view will receive a strongly type model and will do with it what it needs to do with it. In your case, a form will be created with two drop down lists and a submit button. I have left out all your CSS for clarity (just go and add it):
#model WebApplication_Test.Models.CaseViewModel
#using (Html.BeginForm())
{
<div>
#Html.DropDownListFor(
m => m.StatusId,
new SelectList(Model.Statuses, "Id", "Name", Model.StatusId),
"-- Select --"
)
#Html.ValidationMessageFor(m => m.StatusId)
</div>
<div>
#Html.DropDownListFor(
m => m.AppId,
new SelectList(Model.Apps, "Id", "Name", Model.AppId),
"-- Select --"
)
#Html.ValidationMessageFor(m => m.AppId)
</div>
<div>
<button type="submit">Submit</button>
</div>
}
So now you have two drop down lists populated with data. Select a value in each and press the submit button. Your view is bound to a view model and will retain values on form submission. Values in lists are not kept on form submission and will need to be populated again:
[HttpPost]
public ActionResult Index(CaseViewModel model)
{
// Check form validation
if (!ModelState.IsValid)
{
// If validation fails, rebind the lists and send the current view model back
model.Statuses = new List<Status>();
model.Statuses.Add(new Status { Id = 1, Name = "Down" });
model.Statuses.Add(new Status { Id = 2, Name = "Up" });
model.Apps = new List<App>();
model.Apps.Add(new App { Id = 1, Name = "SAP" });
model.Apps.Add(new App { Id = 2, Name = "JAP" });
return View(model);
}
// Form validation succeeds, do whatever you need to do here
return RedirectToAction("Index");
}
I hope this helps.
In the view just add a button in the form like
<button id="b1" Text="Submit"/>
In the controller add an action method to handle the post.
public class CaseController : Controller
{
[HttpPost]
public ActionResult Index(Case case)
{
//Do Something
return View();
}
public ActionResult Index()
{
return View();
}
}
You may also want to look into using Razor and strongly typed views. Makes things much simpler.
another approach is to use mvc ajax call, by doing these you also can pass parameter to controller from simple parameter to a selected row in gridview.
On the view in the button control add onclick property that point to a javascript function and passing parameter. In these sample will get selected row on the gridview
<input id="GenerateData" type="button" value="GenerateData" onclick="generateData(App.grdNameOfGridview.getRowsValues({selectedOnly:true}) [0]);" />
On the view create a javascript function that use ajax to call the controller, note the paramater that can be passing from click button event to the javascript function that will use ajax to call the controller. In this sample i use extjs framework, if you want you can also use jquery as well
generateData= function (recordData) {
var jsonStringContractUnit = JSON.stringify(recordData);
Ext.Ajax.request({
url: '../ControllerName/GenerateData',
method: 'POST',
params: {
SelectedContractUnit: jsonStringContractUnit
},
On the controller the parameter will be pass from view and will be store on SelectedData
public ActionResult GenerateData(string SelectedData)
{
}

How to display assosiated data on second tab based on the data coming under first tab in ASP.NET MVC and EF

I am using MVC application and entityframework,i have two table country and city which has PK_FK relation ship.In my UI i am using two tabs, first tab for countries and second for cities and both are displayed in a grid which is in two partial views.Now what i have to achieve is if i click a country in first tab corresponding country cities should display in second tab rather than complete country cities.How to do that following is the existing code i have done
controller
public ActionResult Index()
{
return View();
}
public ActionResult _gridfirsttab()
{
return PartialView(db.Countries.ToList());
}
public ActionResult _gridsecondtab()
{
return PartialView(db.Citynews.ToList());
}
Index view
<ul>
<li>Tab Header 1</li>
<li>#Html.ActionLink("Tab Header 2", "_gridsecondtab")</li>
<li>>#Html.ActionLink("Tab Header 3", "_gridthirdtab")</li>
</ul>
<div id="tabs-1">
#Html.Action("_gridfirsttab")
</div>
UPDATE
I did like shown below but it is duplicating webgrid, may HTTPGET action also triggering how to prevent it
first partial view grid
#if (grid.HasSelection)
{
conuntry = (firstmvc4.Models.Country)grid.Rows[grid.SelectedIndex].Value;
#Html.Action("_gridsecondtab", new {id =conuntry.id })
}
and created one more HTTPPOST action of first grid
[HttpPost]
public ActionResult _gridsecondtab(int id)
{
// Find the customer by name
var countries = db.Countries.FirstOrDefault(c => c.id == id);
// Get the customers products
var cities = countries.Citynews;
// Send products to the View to be rendered
return PartialView(cities);
}
But it is not properly working rather duplicating first grid itself

How to pass id and name of a #Html.CheckBox via form collection in MVC3

This is my html-
<td>
#{
IEnumerable<SelectListItem> Brands = ViewBag.GetBrands;
foreach (var item in Brands)
{
#Html.CheckBox(item.Text, false)
<label>#item.Text</label><br />
}
}
</td>
Im Posting this controller as JSON data (form collection). How can i get checkbox's text and value in form collection data in controller?
How can i get checkbox's text and value in form collection data in controller?
The correct approach is to use a view model instead of this IEnumerable<SelectListItem>. So basically your model could look like this:
public class BrandViewModel
{
public string Text { get; set; }
public bool Checked { get; set; }
}
and then add a property to your main view model (the one your view is strongly typed to) of type IList<BrandViewModel>:
public IList<BrandViewModel> Brands { get; set; }
and then it's pretty easy:
<td>
#for (var i = 0; i < Model.Brands.Count; i++)
{
#Html.CheckBoxFor(x => x.Brands[i].Checked)
#Html.LabelFor(x => x.Brands[i].Checked, Model.Brands[i].Text)
#Html.HiddenFor(x => x.Brands[i].Text)
}
</td>
and finally you can get rid of any weakly typed FormCollection from your controller action and simply take the view model:
[HttpPost]
public ActionResult SomeAction(IList<BrandViewModel> brands)
{
...
}
or if there are also other properties you need to pass your controller action may take the main view model:
[HttpPost]
public ActionResult SomeAction(MainViewModel model)
{
// the model.Brands collection will be automatically bound here
...
}
I managed to get ID by -
#Html.CheckBox(item.Text, false, new {item.Value})
First You have to perform post back to server.
#using (Html.BeginForm("actionname", "controller",
FormMethod.Post))
//your code
#{
IEnumerable<SelectListItem> Brands = ViewBag.GetBrands;
foreach (var item in Brands)
{
#Html.CheckBox(item.Text, false)
<label>#item.Text</label><br />
}
}
<input type="submit" class="k-button" value="Submit" id="btnSubmit" name="btnSubmit" />
}
Now in the controller you will get the values using form collection
[HttpPost]
public ActionResult actionName( FormCollection collection)
{
collection.keys["checkbox"].value ... your code
}

NullReference error on foreach used to create radiobuttons on POST

I am teaching myself asp .net mvc3. I have a "add property" form which allows user to upload property details to the website. I have been struggling with this error for a long time now.
For simplification, lets consider that I have two tables in my database.
CustomerTypes: The database has 1 Owner, 2 Broker, 3 Commercial etc
Property: This is the table that gets populated by the form.
I use CustomerTypes (and other such tables) to create radio buttons. The user fills the form and selects a choice for "customer type". However, I get an "object reference not set to an instance of an object" error on submit. This is is because "null" is
set for Model.CustomerTypes. However, Model.CustomerTypes is only used to create radio buttons. I am not sure what is wrong. The code is below:
View:
#model Website.ViewModels.AddPropertyViewModel
<fieldset>
<legend>Property</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Property.CustomerType)
#foreach (var item in Model.CustomerTypes)
{
#Html.RadioButtonFor(model => model.Property.CustomerType, Convert.ToInt32(item.Value)) #item.Text
}
</div>
...
AddPropertyViewModel:
namespace Website.ViewModels
{
public class AddPropertyViewModel
{
public Property Property { get; set; }
...
public IEnumerable<SelectListItem> CustomerTypes { get; set; }
...
}
Controller:
public ActionResult AddProperty()
{
AddPropertyViewModel viewModel = new AddPropertyViewModel
{
...
CustomerTypes = websiterepository.GetCustomerTypeSelectList(),
...
};
return View(viewModel);
GetCustomerTypeSelectList functions is:
public IEnumerable<SelectListItem> GetCustomerTypeSelectList()
{
var customerTypes = from p in db.CustomerType
orderby p.CustomerTypeDescription
select new SelectListItem
{
Text = p.CustomerTypeDescription,
Value = SqlFunctions.StringConvert((double)p.CustomerTypeId)
};
return customerTypes;
}
The value in POST is set for Property_CustomerType correctly based on the selection
--- Added further info ---
I start the form as:
#using (Html.BeginForm("AddProperty", "Property", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
...
}
The controller is:
[HttpPost]
public ActionResult AddProperty(AddPropertyViewModel viewModel)
{
if (ModelState.IsValid)
{
//
if (viewModel.File1.ContentLength > 0)
{
var fileName = Path.GetFileName(viewModel.File1.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data"), fileName);
viewModel.File1.SaveAs(path);
}
var property = viewModel.Property;
websiterepository.Add(property);
return RedirectToAction("Index", "Home");
}
return View(viewModel);
}
Here is a screenshot of error:
I have tried submitting the form commenting these radio buttons and it works.
The issue is that CustomerTypes isn't populated when your render the view after posting to the server.
If we look at the flow of actions being performed we see that
You populate the CustomerTypes collection before rendering the
inital page
You post your data back to the server but do not
preserve the CustomerTypes collection (Because there's no need to)
You render the view again but this time without populating
CustomerTypes.
Kaboom!
Populating the CustomerTypes property before you return the view for the second time should fix your problem:
[HttpPost]
public ActionResult AddProperty(AddPropertyViewModel viewModel)
{
[...]
viewModel.CustomerTypes = websiterepository.GetCustomerTypeSelectList();
return View(viewModel);
}

Categories

Resources