Pass id from view to controller - asp.net-mvc

Actually I'm the beginner in the MVC. And simple question:
For example I have ViewModel for the page of Category:
public class CategoryViewModel
{
public int ProductId {get;set;}
public int CategoryId {get;set;}
public string ProductName {get;set;}
public string CategoryName {get;set;}
}
In the controller I just pass CategoryId and CategoryName to the view:
public ActionResult Index()
{
CategoryViewModel categoryViewModel = new CategoryViewModel();
categoryViewModel.CategoryId = catId; \\Get from DB
categoryViewModel.CategoryName = catName; \\Get from DB
return View("Category", categoryViewModel);
}
Then on the View I need to add Product to this Category:
<form action=#Url.Action("AddProduct", "Category") method="POST" enctype = "multipart/form-data">
<textarea name ="ProductName"></textarea>
<input type="submit" value="Add"/>
</form>
And in the controller for AddProduct:
[HttPost]
public ActionResult AddPost(CategoryViewModel categoryViewModel)
{
var productName = categoryViewModel.ProductName;
var categoryId = ?
ProductRepository.AddProductToCategory(productName, categoryId);
return new EmptyResult();
}
Question: How to get the CategoryId? Or maybe there is another approach?

Change your view to include a control for the CategoryId property
#model CategoryViewModel
#using(Html.BeginForm("AddProduct", "Category"))
{
#Html.HiddenFor(m => m.CategoryId)
#Html.TextAreaFor(m => m.ProductName)
<input type="submit" value="Add" />
}
Note, always use strongly types html helpers to generate your html.

Thx for Stephen Muecke
Also you can pass id from (form self) and another properties you want, but you must definition in input action method.
#model CategoryViewModel
#using (Html.BeginForm("AddProduct", "Category", new { id = Model.CategoryId }, FormMethod.Post, new { }))
{
#Html.TextAreaFor(m => m.ProductName)
<input type="submit" value="Add" />
}
Action method :
[HttPost]
public ActionResult AddPost(CategoryViewModel categoryViewModel,int id)
{
var productName = categoryViewModel.ProductName;
var categoryId = id
ProductRepository.AddProductToCategory(productName, categoryId);
return new EmptyResult();
}
i hope this help you.

Related

How to pass #HiddenFor value on post method

This is my ViewModel:
public class TestViewModel
{
public Object p1{ get; set; }
public Type p2{ get; set; }
}
public class MainViewModel
{
public testViewModel test1;
}
This is my View:
#model mainViewModel
#using (Html.BeginForm("updateAction", "controller", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
<fieldset>
#Html.EditorFor(x => x.test1, "editorView")
</fieldset>
}
EditorView.cshtml
#model testViewModel
//<input type="hidden" value="#Html.AttributeEncode(Model.p2)" id="p2" name="p2" />
#Html.HiddenFor(x => x.p2)
Controller method
[HTTPPost]
public ActionResult updateAction(mainViewModel md)
{
//ModelState.Clear();
return View("Index");
}
Now on post method I couldn't get the value of P2 variable. I tried most possible ways to get hidden value on post method but none of them work. I think something with Type property which I was not able to populate.
Please suggest me the way to get the hidden value on controller post method.

BeginForm in ChildAction uses wrong id

There is something simple I don't understand with ChildActions.
I've created a simple View for a model, that loads a child action with a form.
The child action has another model than its parent, with a different id property.
Html.HiddenFor(m => m.Id) still outputs the parents id, although #Model.id outputs the correct value!
Can't I reliably use the Helper methods in ChildActions, or is this a known bug?
HomeController
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new Models.HomeModel { id = 1, message = "bugmodel" };
return View(model);
}
[HttpGet]
[ChildActionOnly]
public ActionResult Child(int id)
{
var model = new Models.HomeChildModel { id = 100, parentId = id, childMessage = "My Child message" };
return PartialView(model);
}
[HttpPost]
[ActionName("Child")]
[ValidateAntiForgeryToken()]
public ActionResult ChildPost(Models.HomeChildModel model)
{
return RedirectToAction("Index");
}
}
Models
public class HomeModel
{
public int id { get; set; }
public string message { get; set; }
}
public class HomeChildModel
{
public int id { get; set; }
public int parentId { get; set; }
public string childMessage { get; set; }
}
Home view
#model ChildActionBug.Models.HomeModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#Html.DisplayFor(m=>m.id)
#Html.DisplayFor(m=>m.message)
#Html.Action("Child", new { id = Model.id })
**Child view**
#model ChildActionBug.Models.HomeChildModel
<h3>Child here</h3>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.HiddenFor(m=>m.id)
#Html.HiddenFor(m=>m.parentId)
#Html.EditorFor(m=>m.childMessage)
<div>Child Model ID: #Model.id</div>
<button type="submit">Save</button>
}
Based on the answer given in the SO question I posted in the comment, you're better off explicitly creating the hidden fields
ASP.Net MVC Html.HiddenFor with wrong value
That's normal and it is how HTML helpers work. They first use the
value of the POST request and after that the value in the model. This
means that even if you modify the value of the model in your
controller action if there is the same variable in the POST request
your modification will be ignored and the POSTed value will be used.
So instead, hand craft the hidden fields:
<input type="hidden" name="Id" value="#Model.Id" />
<input type="hidden" name="ParentId" value="#Model.ParentId" />
<input type="hidden" name="ChildMessage" value="#Model.ChildMessage" />

How do I get a strongly typed DropDownList to bind to a control Action

I've just started a new MVC project and I'm having trouble getting the post result from a form.
This is my Model Class :
public class User
{
public int id { get; set; }
public string name { get; set; }
}
public class TestModel
{
public List<User> users { get; set; }
public User user { get; set; }
public SelectList listSelection { get; set; }
public TestModel()
{
users = new List<User>()
{
new User() {id = 0, name = "Steven"},
new User() {id = 1, name = "Ian"},
new User() {id = 2, name = "Rich"}
};
listSelection = new SelectList(users, "name", "name");
}
}
This is my view class
#model MvcTestApplicaiton.Models.TestModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm())
{
#Html.DropDownListFor(x => x.user, #Model.listSelection)
<p>
<input type="submit" value="Submit" />
</p>
}
#if (#Model.user != null)
{
<p>#Model.user.name</p>
}
And this is my controller :
public class TestModelController : Controller
{
public TestModel model;
//
// GET: /TestModel/
public ActionResult Index()
{
if(model ==null)
model = new TestModel();
return View(model);
}
[HttpPost]
public ActionResult Test(TestModel test)
{
model.user = test.user;
return RedirectToAction("index", "TestModel");
}
}
The drop down list appears just fine but I can't see to get the ActionResult Test function to run. I thought it would just bind itself with reflection but whatever is wrong, I can't see it.
You have two main errors in your code.
As Brett said you're posting to the Index method, but you don't have Index method that supports POST verb. The easiest way to fix is to change Html.BeginForm() with Html.BeginForm("Test", "TestModel")
You're using Html.DropDownListFor in a wrong way. You could pass only a value types there, because don't forget that the View will generate an HTML page. So instead of User in your Model you should have an UserID and in your View you should have #Html.DropDownListFor(x => x.UserID, #Model.listSelection). And finally in your Action you should query your data source to get the details for the user with this ID.
Hope this helps.
Looks like you're posting back to index. Either use a GET Test() action method, or specify the ACTION parameter in BeginForm().
For example,
#using (Html.BeginForm("Test", "TestModel"))
{
#Html.DropDownListFor(x => x.user, #Model.listSelection)
<p>
<input type="submit" value="Submit" />
</p>
}
Or use a view named Test (rename index.cshtml to test.cshtml):
public ActionResult Test()
{
if(model ==null)
model = new TestModel();
return View(model);
}

How to create Static Dropdownlist values in MVC Model

How can I prepare a model for Dropdownlist static values (not retrieved from database) like enum or list in MVC Model so that it could be used many times in a project? I would appreciate if you can give a good article? Thanks.
As always you could start with a view model:
public class MyViewModel
{
public string SelectedValue { get; set; }
public IEnumerable<SelectListItem> Values
{
get
{
return new[]
{
new SelectListItem { Value = "1", Text = "Item 1" },
new SelectListItem { Value = "2", Text = "Item 2" },
new SelectListItem { Value = "3", Text = "Item 3" },
};
}
}
}
then a controller:
public ActionResult Index()
{
var model = new MyViewModel();
return View(model);
}
and finally a view:
#model MyViewModel
#Html.DropDownListFor(x => x.SelectedValue, Model.Values)
For enums you could use some of the many posts out there illustrating custom helpers. Here's one blog post illustrating such helper: http://blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums.aspx
Finally I have found the solution by describing the parameters as hidden input. I am not sure if there is a more elegant method in order to pass the parameters from View to Controller. Thank you so much for your good sample. I also marked as helpful all of your replies. Here is my final code for those who might encounter a similar problem:
ApplicantViewModel:
public class ApplicantViewModel
{
public IEnumerable<Applicant> Applicants { get; set; }
//Codes for Dropdownlist values
public string SelectedValue { get; set; }
public IEnumerable<SelectListItem> Values
{
get
{
return new[]
{
new SelectListItem { Value = "pdf", Text = "Pdf" },
new SelectListItem { Value = "excel", Text = "Excel" },
new SelectListItem { Value = "word", Text = "Word" }
};
}
}
}
ApplicantController:
public ViewResult Reporting()
{
var model = new ApplicantViewModel();
return View(model);
}
public ActionResult RenderReport(string SelectedValue, string name, string fileName, string dataSource, string table, string filter)
{
//Codes for rendering report
...
}
Reporting.cshtml:
#model MyProject.Models.ApplicantViewModel
#using (Html.BeginForm("RenderReport", "Applicant", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
<div>
#Html.DropDownListFor(model => model.SelectedValue, Model.Values, "-- select an option --")
<input type="hidden" name="name" value="Report1"/>
<input type="hidden" name="fileName" value="image rapor"/>
<input type="hidden" name="dataSource" value="ApplicantDataset"/>
<input type="hidden" name="table" value="ApplicantsView"/>
<input type="hidden" name="filter" value="David"/>
<input type="submit" value="submit" />
</div>
}

primary keys in form for post-back?

I have an asp.NET mvc 3 with razor website. I have a web page that is displaying a list of data from a database in a form such as:
<input type="text" name="blah1" value="blah" />
<input type="text" name="blah2" value="blahblah" />
<input type="text" name="blah3" value="blahblah" />
Each row above is assoicated with a primary key. When the user hits submit and posts back the FormCollection to the controller.. how do I go about getting the primary keys of each blah? Do I add a hidden field for each row that contains the primary key of that row? If so, how do I know which blah it is associated with as the FormCollection is just a dictionary?
I would recommend you using a view model:
public class MyViewModel
{
public string Id { get; set; }
public string Text { get; set; }
}
and then in your controller action you would send a list of those models to the view:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new[]
{
new MyViewModel { Id = "1", Text = "blah" },
new MyViewModel { Id = "2", Text = "blahblah" },
new MyViewModel { Id = "3", Text = "blahblah" },
};
return View(model);
}
[HttpPost]
public ActionResult Index(IEnumerable<MyViewModel> model)
{
// Here you will get a collection of id and text for each item
...
}
}
and the view you could use hidden fields for the id and a textbox for the value:
#model IEnumerable<MyViewModel>
#using (Html.BeginForm())
{
#Html.EditorForModel()
<input type="submit" value="OK" />
}
and the corresponding editor template (~/Views/Shared/EditorTemplates/MyViewModel.cshtml):
#model MyViewModel
#Html.HiddenFor(x => x.Id)
#Html.TextBoxFor(x => x.Text)

Resources