I have a model as below
public class TestModel
{
public string SE { get; set; }
}
Then i have an interface and implementing class, Businesslogic class as below.
public interface ITest
{
List<TestModel> SE();
}
public class Test : ITest
{
public List<TestModel> SE()
{
SEBLL B=new SEBLL();
List<TestModel> lstSeries = new List<TestModel>();
lstSeries = B.SE();
return lstSeries;
}
}
my Business logic class where i bind data from database or sometimes manually
public class SEBLL
{
public List<TestModel> SE()
{
List<TestModel> e = new List<TestModel>();
e.Add(new TestModel{ SE = "A" });
e.Add(new TestModel{ SE = "B" });
return e;
}
}
my controller
public ActionResult Index()
{
ITest s = new Test();
List<TestModel> lstSeries = s.SE();
return View(lstSeries);
}
Finally here is the stronly typed view.
#model IEnumerable<TestModel>
foreach (var item in Model)
{
<div>
<label>
#Html.RadioButtonFor(m => item.SE, item.SE, new { #id = "SE", #class = "radio" })
SE #item.series
</label>
</div>
}
I need both of the Radiobuttons to be unchecked intially.
I am bit new to MVC, radiobutton list is populated with 2 values, but always anyone value is being selected when view initially loads. i tried setting checked html property but that did not help.
please let me know where am i going wrong in the whole process.
Correct me with the process too if i am following wrong flow.
Related
Selected value is not coming when I am trying to check, drop down list is showing all the names, but when I am trying to show the selected value of the dropdownlist in the controller, option is not coming.
Controller:
public ActionResult Index1()
{
Class1 cs1 = new Class1();
return View(cs1);
}
[HttpPost]
public ActionResult Index1(Class1 cs)
{
var selecteditem = cs.psudetail.Find(p => p.Section_PSU == cs.psudetail.ToString());
if (selecteditem != null)
{
}
}
Model class:
namespace WebApplication1.Models
{
public class Class1
{
public List<PSUMaster> psudetail
{
get
{
PSUEntities pe = new PSUEntities();
return pe.PSUMasters.ToList();
}
}
}
}
And the View with Model:
#model WebApplication1.Models.Class1
#{
ViewBag.Title = "Index1";
}
<br />
#Html.DropDownListFor(m => m.psudetail, new SelectList(Model.psudetail, "S_no", "Section_PSU"), "--Select PSU--")
You need to have a property that can "store" the selection you make in the list. Extend the view model (Class1) to include a property SelectedPSU. I guess that S_no in the PSUMaster is the ID, and of type integer. Otherwise adjust the code accordingly!
I have also changed the list to be just a list, and then the controller can worry about populating it. This pattern fits MVC better (keep the model simple).
Updated class:
namespace WebApplication1.Models
{
public class PsuViewModel
{
public int SelectedPSU { get; set; }
public List<PSUMaster> PSU { get; set; }
}
}
Next, the controller has to be updated to pass the list to the view model in the GET Index method:
public ActionResult Index1()
{
var pe = new PSUEntities();
return View(new PsuViewModel {
PSU = pe.PSUMasters.ToList()
});
}
Now we can use the SelectedPSU property in our view:
#model WebApplication1.Models.Class1
#{
ViewBag.Title = "Index1";
}
<br />
#Html.DropDownListFor(m => m.SelectedPSU, new SelectList(Model.PSU, "S_no", "Section_PSU"), "--Select PSU--")
...and we can get the ID in the controller:
[HttpPost]
public ActionResult Index1(PsuViewModel model)
{
var pe = new PSUEntities();
var selectedPsu = pe.PSUMasters.FirstOrDefault(p => p.S_no == model.SelectedPSU);
if (selectedPsu != null) {
// ...
}
}
This is my model
public class MessageSetTypeCollection<T> : CollectionBase where T : MessageSetType, new()
{
public string Name { get; set; }
public string[] Tags { get; set; }
public MessageSetType this[int index]
{
get
{
return (MessageSetType)List[index];
}
}
public void Add(MessageSetType value)
{
List.Add(value);
}
}
This is my controller actions
public ActionResult TestAction()
{
MessageSetTypeCollection<MessageSetType> Model = new MessageSetTypeCollection<MessageSetType>();
Model.Add(new MessageSetType()
{
Alert = "test" // Alert is a public property of the MessageSetType class
});
Model.Add(new MessageSetType()
{
Alert = "test2"
});
return View(Model);
}
[HttpPost]
public void TestAction(MessageSetTypeCollection<MessageSetType> Model)
{
return;
}
In the view I've this code
#using (Html.BeginForm())
{
#Html.EditorFor(a => a[0].Alert)
#Html.EditorFor(a => a[1].Alert)
<input type="submit" value="OK" />
}
When I submit this form to the TestAction action, the inner list into the Model parameter has a Count of 0 elements. Why?
I've also tested this code with List<MessageSetType> model type instead of MessageSetTypeCollection<MessageSetType> and all works correctly. Where is the error?
Please see here source code for List:
http://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs
The implementation is pretty different. You don't have a collection of type MessageSetType on which your indexer should work.
I think you can use source code of to adjust your model: MessageSetTypeCollection.
I've resolved inheriting the MessageSetTypeCollection<T> from List<T> instead of CollectionBase
public class MessageSetTypeCollection<T> : List<T> where T : MessageSetType, new()
{
//Omissis
}
I'm trying to post data from a bunch of text fields using the following:
Controller:
[HttpGet]
public ActionResult Order()
{
OrderViewModel vm = new OrderViewModel();
vm.Id = "some id";
List<IOrderItem> itemList= new List<IOrderItem>();
for (int i = 0; i <= 10; i++)
{
OrderItem x = new OrderItem();
x.ItemId = i + "";
itemList.Add(x);
}
vm.OrderItemList = itemList;
return View(vm);
}
[HttpPost]
public IActionResult Order(OrderViewModel model)
{
return View("blabla");
}
These are the models:
public class OrderViewModel : B.IOrderItemViewModel
{
private List<IOrderItem> orderItems;
public List<IOrderItem> OrderItemList
{
get { return orderItems; }
set { orderItems = value; }
}
private string orderId;
public string Id
{
get { return orderId; }
set { orderId = value; }
}
}
public class OrderItem : IOrderItem
{
private string orderItemId;
public string ItemId
{
get { return orderItemId; }
set { orderItemId = value; }
}
private string _description;
public string Description
{
get { return _description; }
set { _description = value; }
}
}
this is the view:
#model OrderViewModel
#using (Html.BeginForm("Order", "Home", FormMethod.Post))
{
#for (int i = 0; i < Model.OrderItemList.Count; i++)
{
#Html.HiddenFor(x => x.OrderItemList[i].ItemId)
#Html.TextBoxFor(x => x.OrderItemList[i].Description)
<br />
}
<input type="submit" value="submit" />
}
Here is the problem - The interfaces are in another project, let's call it B. I reference B in the project.json file for the main project, A. In B, I just defined the two interfaces the are inherited above.
If I do not use any interfaces, and I just use the objects
e.g. instead of :
List<IOrderItem> OrderItemList
I use :
List<OrderItem> OrderItemList
When I run the project, and hit the view, I see the textboxes. I fill in some data and hit submit. It goes to the controller as expected. If I put a breakpoint in the HttpPost actionresult method, and look at the model, I can see all the data I entered. Perfect.
If I use the code above, where I am inheriting from some interfaces, it does not work. The view loads, I enter in some data, I post, it hits the breakpoint, but the model is empty and it's all null.
Any ideas / help would be greatly appreciated!
You cant bind to interfaces. The process of model binding involves first initializing your model (internally the DefaultModelBinder uses Activator.CreateInstance()) , but you can't initialize an interface (how would it know which type to initialize), which is why
public List<OrderItem> OrderItemList { get; set; }
works, but
public List<IOrderItem> OrderItemList { get; set; }
wont.
This article discusses it more detail and includes a section on creating a custom Abstract Model Binder that may solve your problem.
I have two dropdown lists and two textboxes
Search By: ByHtml.DropDownList("Search1", "Please Select...")
Html.TextBox("searchString1")
Search By: Html.DropDownList("Search2", "Please Select...")
#Html.TextBox("searchString2")
<input type="submit" value="Filter" />
When I make my selection from whichever DDL and type text into the textbox and hit filter my search returns, however after the search the text remains in the textbox, is there a way of clearing it after the search so that the textbox is empty again? I tried
ModelState.Remove("");
but it didn't work.
A sample from My controller code is
public class MainController : Controller
{
private DBEntities db = new DBEntities();
// GET: /Main/
public ActionResult Index(string searchString1, string searchString2, string Search1, string Search2)
{
//Create a Dropdown list
var SearchOptionList = new List<string>();
SearchOptionList.Add("LandLord");
SearchOptionList.Add("Postcode");
SearchOptionList.Add("Street Address");
ViewBag.Search1 = new SelectList(SearchOptionList);
ViewBag.Search2 = new SelectList(SearchOptionList);
var mylist = from m in "mydatabase" select m;
//This statement runs if the user selects a parameter from Search2 and leaves Search1 empty
if (String.IsNullOrEmpty(Search1) && !String.IsNullOrEmpty(Search2))
{
if (Search2 == "Postcode")
{
mylist = mylist.Where(s => s.Postcode.Contains(searchString2));
}
if (Search2 == "LandLord")
{
mylist = mylist.Where(s => s.Name.Contains(searchString2));
}
if (Search2 == "Street Address")
{
mylist = mylist.Where(s => s.StreetAddress.Contains(searchString2));
}
}
return View(mylist.ToList());
}
Your should have a view model containing properties searchString1 and searchString2 and the select lists
public class SearchVM
{
public string searchString1 { get; set; }
public string searchString2 { get; set; }
public SelectList SearchList1 { get; set; }
public SelectList SearchList2 { get; set; }
}
Controller
public ActionResult Search()
{
SearchVM model = new SearchVM();
model.SearchList1 = new SelctList(...);
model.SearchList2 = new SelctList(...);
return View(model);
}
View
#model SearchVM
#using(Html.BeginForm())
{
....
#Html.DropDownListFor(m => m.searchString1, Model.SearchList1, "--Please select--")
#Html.DropDownListFor(m => m.searchString2, Model.SearchList2, "--Please select--")
....
}
Post
[HttpPost]
public ActionResult Search(SearchVM model)
{
// to clear all modelstate and reset values
ModelState.Clear();
model.searchString1 = null;
model.searchString2 = null;
// or to clear just one property and reset it
ModelState.Remove("searchString1");
model.searchString1 = null;
// repopulate select lists if your returning the view
return View(model);
}
At the end of my public ActionResult Index method but before return View() I placed the following code which worked perfectly
ModelState.Remove("searchString1");
ModelState.Remove("searchString2");
ModelState.Remove("Search1");
ModelState.Remove("Search2");
I know is an old question, but I fall in the same issue. So I put my solution.
View:
#Html.TextBox("Search", null, new { #autofocus = "autofocus" })
Controller:
ViewBag.Search= null;
ModelState.Remove("Search");
return View(list.ToList());
Hope to help someone
Using a few answers here, I ended up using a Tuple<> with two Models for a single View. For simplicity, tuple.Item1 has a number known in the view, and I'm submitting info for tuple.Item2 to its controller. I want to send back the value of tuple.Item1.num in the submitted tuple.Item2, for the specific member tuple.Item2.num.
Currently, I have this for the message submission:
#using (Html.BeginForm(null, null, FormMethod.Post, new { id = "createMessage", #action = "/api/Message" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.Hidden("ID", #Model.Item2.ID)
<div class="editor-field">
#Html.TextArea("Text", #Model.Item2.Text)
#Html.ValidationMessageFor(tuple => tuple.Item2.Text)<br />
</div>
<input type="submit" value="Post Discussion" />
}
So, I'd like to have something sending the value of tuple.Item1.num within the Item2 (Message) Model posted to the Controller. How would I do this?
Mind you, I'm verrry new to the MVC and ASP.net frameworks, so I likely have some things mixed up. I understand that this HtmlHelper knows it's working with MessageController due to its #action attribute, but I'm still confused on how it's posting values to it. Any help would be great, thanks!
As per requested, my models:
DrugEntry.cs
namespace Project.Models
{
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using FileHelpers;
[DelimitedRecord(",")]
[Table("DRUGS")]
public class DrugEntry
{
private string ndc;
private string dosage;
private string brand;
private string generic;
private string currentStatus;
public DrugEntry()
{
this.ndc = string.Empty;
this.dosage = string.Empty;
this.brand = string.Empty;
this.generic = string.Empty;
this.currentStatus = "good"; // By default, a drug has no shortages associated with it, and thus is considered 'good'
}
public DrugEntry(string ndc, string dosage, string brand, string generic, string currentStatus)
{
this.ndc = ndc;
this.dosage = dosage;
this.brand = brand;
this.generic = generic;
this.currentStatus = currentStatus;
}
[Key]
[Column("NDC")]
public string NDC
{
get
{
return this.ndc;
}
set
{
this.ndc = value;
}
}
[Column("DOSAGE")]
public string Dosage
{
get
{
return this.dosage;
}
set
{
this.dosage = value;
}
}
[Column("BRAND_NAME")]
public string Brand
{
get
{
return this.brand;
}
set
{
this.brand = value;
}
}
[Column("GENERIC_NAME")]
public string Generic
{
get
{
return this.generic;
}
set
{
this.generic = value;
}
}
[Column("CURRENT_STATUS")]
public string CurrentStatus
{
get
{
return this.currentStatus;
}
set
{
this.currentStatus = value;
}
}
}
}
Message.cs
namespace Project.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;
using FileHelpers;
[Table("MESSAGE")]
public class Message
{
private int id;
private int shortageID;
private string ndc;
private string user;
private DateTime date;
private string text;
[Key]
[Column("ID")]
public int ID
{
get
{
return this.id;
}
set
{
this.id = value;
}
}
[Column("SHORTAGE_ID")]
public int ShortageID
{
get
{
return this.shortageID;
}
set
{
this.shortageID = value;
}
}
[Column("NDC")]
public string NDC
{
get
{
return this.ndc;
}
set
{
this.ndc = value;
}
}
[Column("USER")]
public string User
{
get
{
return this.user;
}
set
{
this.user = value;
}
}
[Column("DATE")]
public DateTime Date
{
get
{
return this.date;
}
set
{
this.date = value;
}
}
[Column("TEXT")]
public string Text
{
get
{
return this.text;
}
set
{
this.text = value;
}
}
}
}
Use ViewModels
Instead of using a tuple, I would recommend to use a ViewModel. A ViewModel is just a simple class that you specifically create to meet the requirements of your view.
A ViewModel is an Asp Mvc standard, you don't modify a model just for the view, instead you create ViewModels.
What is ViewModel in MVC?
You would setup your view model like so.
// You typically name your ViewModel to the View
// that it represents.
public class MessageSubmission
{
public Message Message { get; set; }
public DrugEntry DrugEntry { get; set; }
}
ViewModels should be stored in their own folder. Create a folder called ViewModels and store them there. The following is a folder structure of an applicaton created by Microsoft, notice the ViewModels folder?
View
Since you are using weakly-typed html extensions, I would suggest the following.
#model MyMvcApplication1.ViewModels.MessageSubmission
#using (Html.BeginForm(null, null, FormMethod.Post, new { id = "createMessage", #action = "/api/Message" }))
{
#Html.ValidationSummary(true)
#Html.Hidden("ID", #Model.Message.ID)
<!-- // You can assign the DrugEntry.NDC, to a Message.NDC like this -->
#Html.Hidden("NDC", #Model.DrugEntry.NDC)
<div class="editor-field">
#Html.TextArea("Text", #Model.Message.Text)
#Html.ValidationMessageFor(model => model.Message.Text)<br />
</div>
<input type="submit" value="Post Discussion" />
}
Controller
Simply setup your controller like you normally would.
[HttpPost]
public ActionResult Message(Message message)
{
// Add your stuff here.
}
The MVC default model binder automatically assigns the values from the view page(ID,NDC,Text) to the waiting model in the controller (Message.ID, Message.NDC, Message.Text)
The binder aligns the fields by comparing the ID of the html controls to the properties of the model.
View | Model Properties
------------------------------
Hidden.ID | Message.ID
Hidden.NDC | Message.NDC
TextArea.Text | Message.Text
You can try this in ajax
#using (Ajax.BeginForm("ActionOfItem2", "ControllerOfItem2", new AjaxOptions { UpdateTargetId = "UpdateDiv"}))
{
#Html.Hidden("ID", #Model.Item2.ID)
<input type="submit" value="Post Discussion" />
}
Controller
public ReturnType ActionOfItem2(string ID)
{
// Use the ID here
}