I am using Razor HtmlHelpers.
using the code below i tried to print the value of ViewItemDto but it always show 0 for using #Html.TextBoxFor or any #Html...For(x=>..) method.
Does anybody have a idea why this is happening?
Note - The method is returning proper value as i can debug and see the value in debug window on views side.
[DataContract]
[Serializable]
public class ViewItemDto
{
[DataMember]
public decimal ViewItemId { get; set; }
[DataMember]
public string ItemName { get; set; }
}
From Controller Return
public ActionResult Index()
{
ViewItemDto viewItem = new ViewItemDto();
viewItem.ItemName = "OldData";
viewItem.ViewItemId = 10;
return View(viewItem);
}
public PartialViewResult SaveData(ViewItemDto viewItem)
{
viewItem.ItemName = "NewData";
viewItem.ViewItemId = 100;
return PartialView("ViewUserControl1", viewItem);
}
On View ViewUserControl1
#model Testing.Models.ViewItemDto
<div id="divSave">
#using (Ajax.BeginForm("SaveData", "Home", new AjaxOptions()
{
UpdateTargetId = "divSave",
OnSuccess = "OnSuccess",
InsertionMode = InsertionMode.Replace
}))
{
#Html.TextBoxFor(x => x.ViewItemId)//Shows 10
#Html.TextBox("ID", Model.ViewItemId) //Shows proper value 100
#Html.TextBoxFor(x => x.ItemName)//Shows oldData value
<input type="submit" name="name" value="Submit" />
}
and Index.cshtml
#model Testing.Models.ViewItemDto
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
#Html.Partial("ViewUserControl1", Model);
Shouldn't you be:
return PartialView(viewItem);
instead of:
return viewItem;
By changing the code of your controller to the following it worked here:
public PartialViewResult SaveData(ViewItemDto viewItem)
{
viewItem.ViewItemId = 100;
return viewItem;
}
I was unabled to reproduce your problem, since the code provided not even compiled.
Related
I'm very new to MVC and I'm not sure quite how the forms work. Here's what i want to do:
So I've got two text boxes and an enter button in a form I want to put two values into the textboxes and use them in my external link. Here's the code I am trying to use, i know it's not correct at all but should show you what I'm trying to do:
View:
#model Test.Models.Home
#{
ViewBag.Title = "Main";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm("GetMessage()", "Home", FormMethod.Post))
{
#Html.Label("Location1: ")
#Html.TextBoxFor(model => model.Location1)
#Html.ValidationMessageFor(model => model.Location1)
#Html.Label("Location2: ")
#Html.TextBoxFor(model => model.Location2)
#Html.ValidationMessageFor(model => model.Location2)
<button type="submit">Enter</button>
}
Controller:
using System.Web.Mvc;
using BBWebApp.Models;
namespace Test.Controllers
{
public class HomeController : Controller
{
public ActionResult Main()
{
//var name = new Home() { Name = "Google maps API" };
return View();
}
[HttpPost]
public ActionResult Location(Home model)
{
if (ModelState.IsValid)
{
//TODO: SubscribeUser(model.Email);
}
return View("Main", model);
}
[HttpPost]
public ActionResult GetMessage()
{
return Redirect("https://example.com/" + Location1 + "/" + Location2);
}
}
}
Model:
public class Home
{
public string Location1 { get; set; }
public string Location2 { get; set; }
public string Name { get; set; }
}
As you can see I'm trying to get the form to trigger the redirect function under getMessage() but obviously this code is flawed as I don't fully understand how it works. As i said I'm very new to MVC so any help with this would be much appreciated.
This code is very good for starting. Only have some minor problems:
On your view's using block, remove paranthesis from action method
GetMessages
like that
#using (Html.BeginForm("GetMessage", "Home", FormMethod.Post))
{
#Html.Label("Location1: ")
#Html.TextBoxFor(model => model.Location1)
#Html.ValidationMessageFor(model => model.Location1)
#Html.Label("Location2: ")
#Html.TextBoxFor(model => model.Location2)
#Html.ValidationMessageFor(model => model.Location2)
<button type="submit">Enter</button>
{
Then you need to get your model and use variables on your controller's method
[HttpPost]
public ActionResult GetMessage(Home model)
{
return Redirect("https://example.com/" + model.Location1 + "/" + model.Location2);
}
and you are good to go.
This is a sister question from another question I posted (here). Many thanks to #nurdyguy and all of the people who helped me previously. However, I am having an issue where I am unable to pass a list of values to a destination controller that's in another View. My desired output is to send over the complete List object but right now I am getting a value count of zero (0) when it gets to the controller.
Here is my Model:
using System.Collections.Generic;
namespace Foo.Models
{
public class FooViewModel
{
public List<Foo> FooCollection = new List<Foo>();
/*Contains two properties
string CarName {get; set;}
string Color {get; set;}
List<Features> Features = new List<Features>();
*/
}
}
My View
#model Foo.Models.FooViewModel
#{
var RedCars = Model.FooCollection.Where(c => c.Color == "Red").ToList();
... //{yellow, blue, green}
}
<div id="FooCollection">
<section class="no-padding-top no-padding-bottom">
<div class="container-fluid">
<div class="public-user-block block">
<div class="row d-flex align-items-center">
<!--Red Cars-->
#using (Ajax.BeginForm("../Bar/Index/Red", null,
new AjaxOptions
{
HttpMethod = "post",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "CarsList"
}, new { id = "RedCarsForm" }))
{
<input type="hidden" name="Cars" value="#RedCars" />
<div id="status-container" class="col-lg-3 d-flex align-items-center">
<button type="submit">#RedAlerts.Count</button>
<strong>Red Cars</strong>
</div>
}
<!-- same structure for yellow, green, blue --!>
</section>
</div>
My Controller:
public ActionResult Index()
{
foreach (var car in db.database.Db_GetCars())
{
model.FooCollection.Add(new Foo()
{
CarName = car.CarName,
Color= car.Color
});
}
return View(model);
}
Destination Controller:
namespace Foo.Controllers
{
public class BarController: Controller
{
BarViewModel model = new BarViewModel();
[HttpPost, Route("/Bar/Index/{color}")]
public ActionResult Index(List<Foo> Cars)
{
//logic goes here
return View(model);
}
}
}
I spent some time digging around the best practices to route data but most places I've went have their forms set up like mine and it seems to work (for them). I even passed (as the second parameter) new { Cars = RedCars } but I still get zero (0). Is there something I am missing? Many thanks in advance!
I have the following viewModel
public class ExerciceViewModel
{
public string Code { get; set; }
public string Titre { get; set; }
public int QuestionCourante { get; set; }
}
the following view
#model MonEcoleVirtuelle.ViewModel.ExerciceViewModel
#{
ViewBag.Title = "Test";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Test</h2>
#using (Html.BeginForm("test", "exercice", FormMethod.Post))
{
#Model.Code <br />
#Model.Titre<br />
#Model.QuestionCourante<br />
<br />
<br />
Model.Code = "Code Modifie";
<input type="submit" value="Post Moi Ca!" name="fini" />
}
and the following controller methods
[HttpPost]
public ActionResult Test(ViewModel.ExerciceViewModel model)
{
if (ModelState.IsValid)
{
return Content(model.Code);
}
return View(model);
}
[HttpGet]
public ActionResult Test()
{
var vm = new ViewModel.ExerciceViewModel { Code = "code1", Titre = "Mon titre", QuestionCourante = 1 };
return View(vm);
}
When I submit the form, the model passed is empty, all properties are reset, not keeping the original values. What am I missing.
thanks
well, instead of #Model.Code which just display the values, you need some inputs.
So #Html.TextBoxFor(m => m.Code) for example
To manage a collection, you can do something like that :
#for (var i = 0; i < Model.Collection.Count; i++) {
Html.TextBoxFor(m => Model.Collection[i].Property)
}
You have not included any input fields in your view.
The #Model.Code etc only output the value of the field. To be able to post back elements they need to be form elements, like inputs. Use something like
#Html.TextBoxFor(p=>p.Code)
to create input fields that can then be posted back.
For a more complete guide see MSDN at http://msdn.microsoft.com/en-us/library/dd410596(v=vs.100).aspx
How to I convert my simple MVC4 todo list application to AJAX?
The ideal answer would give me the steps that would lead to a successful conversion of this example to AJAX.
Note: I don't need an AJAX tutorial so much as an understanding of how the ASP.NET MVC architecture supports it.
Side Question: Why does #Html.EditorFor(model => model.TodoItemToCreate) bring back the value that was typed in even though the view model sets with this.TodoItemToCreate = null?
Model
public class TodosViewModel
{
List<string> todoItems;
public List<string> TodoItems
{
get { return this.todoItems ?? (todoItems = new List<string>()); }
}
[Display(Name="What do you need to do?")]
public string TodoItemToCreate { get; set; }
public bool AcceptTodoItem()
{
bool isThereAnItemToAccept = !string.IsNullOrWhiteSpace(this.TodoItemToCreate);
if (isThereAnItemToAccept)
{
this.TodoItems.Add(this.TodoItemToCreate);
this.TodoItemToCreate = null;
}
return isThereAnItemToAccept;
}
}
Controller
public class TodosController : Controller
{
public ActionResult Index()
{
return View(new TodosViewModel());
}
public ActionResult Create(TodosViewModel todosViewModel)
{
todosViewModel.AcceptTodoItem();
return View("Index", todosViewModel);
}
}
Index View
#model Programming.LearnWeb.Models.TodosViewModel
#{
ViewBag.Title = "Todos";
}
#using (Html.BeginForm("Create", "Todos"))
{
#Html.Partial("List")
#Html.LabelFor(model => model.TodoItemToCreate)
#Html.EditorFor(model => model.TodoItemToCreate)
<input type="submit" value="Create" />
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
List View
#model Programming.LearnWeb.Models.TodosViewModel
#{ int i = 0; }
<table>
#foreach (var todoItem in Model.TodoItems)
{
<tr>
<td>
#Html.Hidden("TodoItems[" + i++ + "]", todoItem)
#todoItem
</td>
</tr>
}
</table>
I got this done on my own - the result is at https://github.com/gabrielgreen/Todos.Mvc if anyone is interested or has any comments.
I put a fair amount of effort in and would appreciate any feedback that indicates if I did it right.
I've been stuck a long time to edit a subcollection of my model, the collection of the model was coming null.
I finally found a solution, but I find it a little dirty:
First my tests datas:
Model object:
public class ContainerObject
{
public String Title { get; set; }
public List<ContainedObject> ObjectList { get; set; }
}
Sub collection object:
public class ContainedObject
{
public int Id { get; set; }
public String Text { get; set; }
public Boolean IsSelected { get; set; }
}
Controller method which generate the object
public ActionResult TestForm()
{
return View(new ContainerObject()
{
Title = "This is a sample title",
ObjectList = new List<ContainedObject>()
{
new ContainedObject(){Id=1, IsSelected = true, Text="ObjectOne"},
new ContainedObject(){Id=2, IsSelected = false, Text="ObjectTwo"},
new ContainedObject(){Id=3, IsSelected = true, Text="ObjectThree"},
new ContainedObject(){Id=4, IsSelected = false, Text="ObjectFour"},
}
});
}
Controller which receive the edited object
[HttpPost]
public ActionResult TestFormResult(ContainerObject filledObject)
{
return View();
}
The view
#model WebTestApplication.Models.ContainerObject
#{
ViewBag.Title = "TestForm";
}
#using (Html.BeginForm("TestFormResult","Home", FormMethod.Post)){
#Html.EditorFor(x => x.Title)
Html.RenderPartial("ContainedObject", Model.ObjectList);
<input type="submit" value="Submit"/>
}
The partial view(ContainedObject.cshtml)
#model IEnumerable<WebTestApplication.Models.ContainedObject>
#{
ViewBag.Title = "ContainedObject";
int i = 0;
}
#foreach (WebTestApplication.Models.ContainedObject currentObject in Model)
{
<br />
#Html.Label(currentObject.Text);
#Html.CheckBox("ObjectList[" + i + "].IsSelected", currentObject.IsSelected);
#Html.Hidden("ObjectList[" + i + "].Id", currentObject.Id);
#Html.Hidden("ObjectList[" + i + "].Text", currentObject.Text);
i++;
}
This is actually working, but I've one problem:
I've to generate names myself and specify the property of the container object
I tried to use Html.EditorFor instead of Html.RenderPartial in the view, the problem is that it generate me the name "ObjectList.[0].Id"(with a additional . between the property name and the accessor).
I also tried to use only #Html.EditorFor in the partial view, but it create vars with the name of the object.
If I don't use any template, it works:
#model WebTestApplication.Models.ContainerObject
#{
ViewBag.Title = "TestForm";
}
#using (Html.BeginForm("TestFormResult", "Home", FormMethod.Post))
{
#Html.EditorFor(x => x.Title)
for (int i = 0; i < Model.ObjectList.Count; i++)
{
<br />
#Html.Label(Model.ObjectList[i].Text);
#Html.CheckBoxFor(m => Model.ObjectList[i].IsSelected);
#Html.HiddenFor(m => Model.ObjectList[i].Id);
#Html.HiddenFor(m => Model.ObjectList[i].Text);
}
<br /><input type="submit" value="Submit"/>
}
But here it's a simple template, but in my real case, I will have much more data, and this will be re-used multiple time. So what is my best option?
You can simplify your code by introducing the EditorTemplate. Here is how:
The main view remains pretty much the same except we replaced RenderPartial with EditorFor:
TestForm.cshtml
#model WebTestApplication.Models.ContainerObject
#{
ViewBag.Title = "TestForm";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm("TestFormResult", "Home", FormMethod.Post)) {
#Html.EditorFor(m => m.Title)
#Html.EditorFor(m => m.ObjectList);
<input type="submit" value="Submit" />
}
Then create a folder named EditorTemplates under Views/Home (assuming your controller is Home):
and add the following template for the ContainedObject:
ContainedObject.cshtml
#model WebTestApplication.Models.ContainedObject
<p>
#Html.DisplayFor(m => m.Text)
#Html.CheckBoxFor(m => m.IsSelected)
#Html.HiddenFor(m => m.Id)
#Html.HiddenFor(m => m.Text)
</p>
The editor will automatically iterate through the list of objects rendering the view for each of them. Hope it helps.
I found this thread while looking for something else related. Denis has the correct answer, but I thought I would add some syntax in case anyone else comes across this:
If you have an editor template named "SomeTemplate.cshtml" you can use it for a list of Item as follows in your view:
#for (var i = 0; i < Model.ObjectList.Count(); i++)
{
#Html.EditorFor(m => m.ObjectList[i], "SomeTemplate")
}
Then in your editor template:
#model WebTestApplication.Models.ContainedObject
<br />
#Html.Label(Model.Text);
#Html.CheckBoxFor(m => m.IsSelected);
#Html.HiddenFor(m => m.Id);
#Html.HiddenFor(m => m.Text);