How do i pass data from a Html.EditorFor to myAction in myController?
This is my Editor:
<div class="editor-label">
#Html.LabelFor(model => model.Quote_Currency)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Quote_Currency, new { })
#Html.ValidationMessageFor(model => model.Quote_Currency)
</div>
This is my controller action:
public ActionResult SaveQuote(FxQuote quote, string Quote_Currency)
{
objQuote.Quote_Currency = Quote_Currency;
dcfx.FxQuotes.InsertOnSubmit(quote);
dcfx.SubmitChanges();
return View();
Here,i was trying to have a parameter with the same name as my Editor but that did not work.
Please help.
You can add a FormCollection collection as an extra parameter to your controller method. That collection will hold all data passed from the view in the controller. You can use the debugger to explore which data is exactly being sent to the controller.
Why dont you just change the action to accept your model?
Something like this:
public ActionResult SaveQuote(ModelType model)
{
objQuote.Quote_Currency = model.Quote_Currency;
dcfx.FxQuotes.InsertOnSubmit(model.Quote);
dcfx.SubmitChanges();
return View();
}
Alternatively you can change it to accept a form collection as mentioned in another answer:
public ActionResult SaveQuote(FormCollection collection)
Hope this helps
Related
I have an ASP.NET MVC 5 project where I need to get a class (with approximately 20 variables) from my controller to a view, and then I need to get the data back to my controller. I know I can use ViewBag variables, but that seems so tedious for that many variables, and I don't want to use a model because the data won't necessarily come from or go to a database. Does anyone know a good way to do this?
Use a view model. Models don't have to be connected to a database. They're very handy for usage in forms. Here's a very simplified example of what you can do:
public class PersonViewModel
{
public string Name {get;set;}
public string Email {get;set;}
// .... etc
}
Load form
[HttpGet]
public ActionResult MyForm()
{
return View(new PersonViewModel());
}
Post form
[HttpPost]
public ActionResult MyForm(PersonViewModel model)
{
if (ModelState.IsValid)
{
// do stuff
}
return View(model);
}
View (bound to PersonViewModel)
#model PersonViewModel
<h1>Person Form</h1>
#using (Html.BeginForm())
{
#Html.LabelFor(m => m.Name)
#Html.TextBoxFor(m => m.Name)
#Html.LabelFor(m => m.Email)
#Html.TextBoxFor(m => m.Email)
<button type="submit">Submit</button>
}
I've just started using MongoDB and i have problem.
While i try to pass object to controller which containts Id (ObjectId), this Id is empty
My View code:
#using (Html.BeginForm()) {
<fieldset>
<legend>Product</legend>
#Html.HiddenFor(model => model.Id)
#Html.EditorFor(model => model.Name)
#Html.EditorFor(model => model.Price)
<input type="submit" value="Save" />
</fieldset>
}
Action:
[HttpPost]
public ActionResult Edit(Product product)
{
_db.Update(product);
return RedirectToAction("Index");
}
Action begins right, i mean, all properties in product are correct but Id (which is mongo's ObjectId) is just empty (Creation date is 1970, rest properties are just zeros)
I dont know what to do...
Please, help.
This happens because mvc don't know how to create ObjectId from string. You can create your own model binder like in this article http://www.joe-stevens.com/2011/06/12/model-binding-mongodb-objectid-with-asp-net-mvc/
For ASP.Net (including Core) MVC the easiest way I found was to use: new ObjectId(yourString) ...This will give you a MongoDB ObjectId from a string and should work with any of your queries.
This is what I've had in mind but of course it doesn't work.
#{
var textBoxData = form.find('input[name="textboxList"]').val();
}
<input type="button" value="Add" title="Add" onclick="location.href='#Url.Action("Create_Add", "Controller", new { textboxList = textBoxData })'" />
How should I pass this? Controller action name and parameter are correct. Just that I don't know how to get the value entered in textbox...
I have trouble with saving a form within a form, so someone suggested this solution. Proxy code would be:
<firstForm>
textboxfor Name
dropdownfor DType
If DTypeDDL value is "List" then
<secondForm>
textboxfor nameOfItem
submitSecondForm (using that method i mentioned above)
</secondForm>
End If
submitFirstForm
</firstForm>
I've been trying to save 2 forms for quite a while now but no luck. This is basically my last resort.
First of all, you should go with a viewmodel oriented html file since you are using MVC (Model, View, Controller):
Create a viewModel:
public class ExampleViewModel
{
public ExampleViewModel()
{
}
public virtual string TextBoxData { get; set; }
}
After, code your html using the viewmodel as model:
#model Models.Views.ExampleViewModel
#using (Html.BeginForm())
{
<div class="editor-row">
<div class="editor-label">
#Html.LabelFor(model => model.TextBoxData)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.TextBoxData)
</div>
</div>
<input type="submit" value="submit" />
}
and your controller:
public ActionResult Example()
{
ExampleViewModel model = new ExampleViewModel();
return This.View(model);
}
[HttpPost]
public ActionResult Example(ExampleViewModel model)
{
string infoEntered = model.TextBoxData;
// Do something with infoEntered
}
Hope this will help you!
If you're using view models, check out this answer: MVC sending data from View to Controller
If you're only interested in sending the data from an input to the action method without view models, you can do that as well:
View:
#using (Html.BeginForm("Edit", "Some", FormMethod.Post))
{
<input type="text" id="myTextBox" name="myTextBox" />
<input type="submit" value="Submit" />
}
Notice the BeginForm line. The first parameter is the Action I want the data to go to, which I named Edit. The next parameter is the Controller I am using, which I named SomeController. You don't add the Controller bit to the name when you're referencing the Controller in BeginForm. The third parameter is telling the form to use the POST method when sending the data to the server.
Controller:
public class SomeController
{
[HttpPost]
public ActionResult Edit(string myTextBox)
{
// Do what you want with your data here.
}
}
If you added more inputs (again, without a view model here), you can add them as parameters to the Edit method. This isn't really the preferred method, though. Look into using a view model. ScottGu has a nice blog post on doing what you need, using view models:
http://weblogs.asp.net/scottgu/archive/2007/12/09/asp-net-mvc-framework-part-4-handling-form-edit-and-post-scenarios.aspx
I am new to MVC3 and am trying to write a blog application as a learning tool.
I've created a database object for the blog post and generated a controller using the Controller with Read/Write actions and views using Entity Framework to control the entity.
I'm having troubles with the edit commands. There are about 6 properties for a blog post but I only want to allow the edit to modify the title and content of the post. My code is as follows:
public ActionResult Edit(int id)
{
blog_Post blog_post = db.blog_Post.Find(id);
return View(blog_post);
}
//
// POST: /Post/Edit/5
[HttpPost]
public ActionResult Edit(blog_Post blog_post)
{
if (ModelState.IsValid)
{
db.Entry(blog_post).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(blog_post);
}
#model BlogVersion1._0.blog_Post
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>blog_Post</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.PostContent)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PostContent)
#Html.ValidationMessageFor(model => model.PostContent)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
The problem that comes about is in the public ActionResult Edit(blog_Post blog_post) method. In the Edit(int id) method, I have put a breakpoint in and I can see that blog_post is being properly passed to the view (including all of its properties populated).
But the blog_post being returned to the [HttpPost] method is missing properties for UserId, DateCreated, etc. An exception is obviously thrown on the db.SaveChanges call as required foreign keys are missing.
How do I ensure that all properties are returned to the second edit method to properly make the update?
Because you are not sending the values of those elements from your form when you do the POST ing. One way to fix this is to keep them inside the form using Hidden Variables
#using(Html.BeginForm())
{
#Html.EditorFor(model => model.Title)
#Html.HiddenFor(model => model.UserId)
<input type="submit" />
}
I think the clean solution is to "Dont use the Domain model in the view, Use a ViewModel with necessary properties for the View. In this case, obviously CreatedDate should not be something the View should supply. It should be something the code will be filled to the object.
So create a ViewModel for this
public class BlogPostViewModel
{
public int ID { set;get;}
public string Title { set;get;}
public string Description { set;get;}
}
and use this for transfering data from View to controller and viceversa
public ActionResult Edit(int id)
{
var domainObject=repo.GetPost(id);
var viewModel=new BlogPostViewModel();
viewModel.ID=domainObject.ID;
viewModel.Title=domainObject.Title;
//map other REQUIRED properties also
return View(viewModel);
}
Your view will be strongly typed to this
#model BlogPostViewModel
#using(Html.BeginForm())
{
#Html.EditorFor(model => model.Title)
#Html.HiddenFor(model => model.Description)
<input type="submit" />
}
In the POST action,map it back to the domain object and save
[HttpPost]
public ActionResult Edit(BlogPostViewModel model)
{
if(ModelState.IsValid)
{
var domainObject=new blog_Post();
domainObject.Title=model.Title;
domainObject.ModifiedDate=DateTime.Now;
//set other properties also
repo.Update(domainObject);
return RedirecToAction("Success");
}
return View(model);
}
Instead of manually mapping properties one by one you can consider using AutoMapper library which does this for you in one line of code!
Just add hidden fields for all other, non-editable properties.
#Html.HiddenFor(model => model.Id)
These field will be included in POST and hence, model binder will correctly put them into your blog_post instance.
On the other side, you should really be using view models - simple POCO classes that will be models for your views. Using entity models directly is not recommended.
Here's some info on that:
ASP.NET MVC ViewModel Pattern
http://stephenwalther.com/archive/2009/04/13/asp-net-mvc-tip-50-ndash-create-view-models.aspx
The model binder will only populate the properties that are POSTed in the HTTP request. Your view only contains Title and PostContent.
You either need to include hidden fields for each of the missing properties. Or just the ID property and then do a database lookup for the rest.
For your case, I think You should rather use the HtmlHelper extension method "EditorForModel" instead of calling "EditorFor" for each property. You are complicating your life using EditorFor on each property (and as gred84 is saying, it doesn't post the non displayed properties in the HTTP request in you context).
In your blog_Post model class you should flag each property that you don't want to be edited with the attribute [HiddenInput(DisplayValue = false)]
Then instead of all your code in the view, you can simply have (simplified - without validation summary)
#using (Html.BeginForm())
{
#Html.EditorForModel()
<input type="submit" value="Save" />
}
At the moment I have this code:
#using (Html.BeginForm("Add", "Review", "Review"))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Review</legend>
<div class="editor-label">
#Html.LabelFor(model => model.TEKST)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.TEKST)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
This will send me to: localhost:4470/Review/Add?Length=6
The thing that I actually want is this url: localhost:4470/Review/Add?tekst=sdfsdf
How can I modify this code that it will use "tekst" as parameter instead of length? And as value the content of the textbox.
UPDATE:
This are my action methods:
public ActionResult Create()
{
return View();
}
public ActionResult Add(string tekst)
{
ViewBag.test = tekst;
return View();
}
In the View page of Create, I would like to have a form, with a textbox or textarea, that sends an action to Add, the content of the textbox or textarea should be in parameter "tekst" of action method "Add"
SOLUTION:
See the post of CD Smith
I'm not sure what your action looks like but as long as it is accepting your model, you have the value for TEKST in your model..
If you need something different then you're View would need to be different as well, you post a Model from the view, you don't send GET parameters by making a POST
Do you have an action that currently takes TEKST as a parameter?
UPDATE
Ok, looking at your action... you don't need to modify your view, you need to modify your actions, try this this will get you what you want.
Change YourModelTypeHere to match your real model type
[HttpPost]
public ActionResult Create(YourModelTypeHere model)
{
return RedirectToAction("Add", new { tekst = model.tekst });
}
public ActionResult Add(string tekst)
{
ViewBag.test = tekst;
return View();
}
You need to modify your view just a tad - remove the parameters from the BeginForm tag
#using (Html.BeginForm())
So the Create action will render the Create View, then POST back to the Create method that has the [HttpPost] annotation. Then the value of TEKST will be sent as a parameter to the Add method as a RedirectToAction and render the Add view
I'm not sure where the "Length=6" is coming from, as I can't see what part of your code would create that URL...
It sounds to me that you're expecting a GET request, but (by default) a form will result in a POST request. Based on your code, I would expect the generated route to be "localhost:4470/Review/Add". Whatever the contents of the form are will be sent as form data.
So in your controller, if your action method looked like this:
[HttpPost]
[ActionName("Add")]
public ActionResult AddViaPost(string tekst)
{
// do something with tekst
}
Then you should get the value of the text box posted correctly to your controller.