Partial Views with different model in Asp.net MVC - asp.net-mvc-4

i have two class as below
Model:-
public class RegisterViewModel
{
public string Email { get; set; }
public AddressPropertyVM AddressProperty { get; set; }
}
public class AddressPropertyVM
{
public string StreetNo { get; set; }
}
Main Form
#model Application.Models.RegisterViewModel
{
#Html.TextBoxFor(m => m.Email)
#Html.TextBoxFor(m => m.FirstName)
#Html.Partial("_AddressPropertyPartial",Model.AddressProperty)
<button type="submit">Register</button>
}
Partial View Form
#model Application.Models.AddressPropertyVM
{
#Html.TextBoxFor(m => m.StreetNo)
}
I am creating asp.net mvc application.
I have create a partial view for AddressPropertyVM.
but we i post form(main form) at that time data of AddressProperty is null.

As per my understanding you want to use one partial view with more than one pages I mean multiple usage of one page in many pages.
Read this article and understand how it works.
Change your code as per article like below.
#Html.Partial("_AddressPropertyPartial",Model.AddressProperty)
To
#Html.Partial("_AddressPropertyPartial", Model.AddressProperty, new ViewDataDictionary() { TemplateInfo = new TemplateInfo() { HtmlFieldPrefix = "AddressProperty" } }

Related

why checkbox wont check on page load?

i have the following database table for the Compounds table (chemical compounds/elements in the periodic table) there are typos in table data so ignore them
the data is :
the controller :
public class CheckboxController : Controller
{
//
// GET: /Checkbox/
testdbEntities db = new testdbEntities();
[HttpGet]
public ActionResult Index()
{
var comps = db.Compounds.Select(c => new CompoundModel { Id=c.Id, CompoundName=c.Name, IsSelected=c.IsSelected}).ToList();
CheckboxVM cvm = new CheckboxVM { checkboxData=comps};
return View(cvm);
}
[HttpPost]
public string Index(IEnumerable<CheckboxVM> collection)
{
return "";
}
}
Model class CompoundModel is:
public class CompoundModel
{
public int Id { get; set; }
public string Code { get; set; }
public string CompoundName { get; set; }
public bool IsSelected { get; set; }
}
and the ViewModel CheckBoxVM:
public class CheckboxVM
{
public string Id { get; set; }
public string CompoundNmae { get; set; }
public bool IsSelected { get; set; }
public IEnumerable<CompoundModel> checkboxData { get; set; }
}
When the page loads it should display check boxes with names and if db table has checked on them (IsSelected=1) then they should be checked.In the post back i need to receive the id, of the user checked checkboxes. At the moment my code does meet the first requirement to check the checked checkboxes based on IsSelected on page load. Is there a way to fix this?
If you need a video with debugging please ask i will be happy to post : )
THE VIEW: (UPDATE)
#model recitejs1.Models.CheckboxVM
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm())
{
foreach (var item in Model.checkboxData)
{
#Html.CheckBoxFor(x=>x.IsSelected, (item.IsSelected)?new{#checked="check"}:null)#item.CompoundName
#Html.HiddenFor(x=>x.Id, item.Id)
#Html.HiddenFor(x=>x.CompoundNmae, item.CompoundName)
}
<br><br>
<input type="submit" name="name" value="Send" />
}
You cannot use a foreach loop to generate form controls. It generates duplicate name attributes (that have no relationship to your model) and duplicate id attributes (invalid html).
Create a custom `EditorTemplate for your model
In /Views/Shared/EditorTemplates/CompoundModel.cshtml
#model recitejs1.Models.CompoundModel
#Html.HiddenFor(m => m.Id)
#Html.HiddenFor(m => m.CompoundName)
#Html.CheckBoxFor(m => m.IsSelected)
#Html.LabelFor(m => m.CompoundName)
Then in the main view
#model recitejs1.Models.CheckboxVM
....
#using (Html.BeginForm())
{
#Html.EditorFor(m => m.checkboxData)
<input type="submit" name="name" value="Send" />
}
The EditorFor() method will generate the correct html for each item in your collection
Note: You should inspect the html before and after you make this change to better understand how model binding works.
Note also that your POST method parameter needs to be
public string Index(CheckboxVM model)
since that's what the view is based on. However the only property of CheckboxVM that you use in the view is IEnumerable<CompoundModel> checkboxData in which case your view should be
#model IEnumerable<CompoundModel>
...
#Html.EditorFor(m => m)
and keep the POST method as it is (but change the GET method)

Passing Model via dropDownListFor() from view to controller

I am trying to pass a Model from my view to my controller using dropDownListFor.
After choosing something from the list it sends the model to my controller but it's content NULL.
This is what i have for the Model
public class Model
{
public int ModelId { get; set; }
[Required]
public string Name { get; set; }
}
This is what my ViewModel looks like
public class ModelVM
{
public List<Model> Models;
public Model SelectModel { get; set; }
public IEnumerable<SelectListItem> ModelItems
{
get { return new SelectList(Models, "ModelId", "Name"); }
}
}
The controller when i put data in the ViewModel looks like this
public ActionResult Index()
{
ModelVM modelVM= new ModelVM()
{
Models = manager.GetAllModels().ToList()
};
return View(modelVM);
}
Finally this is what i have in the View for the dropDownList
#using (Html.BeginForm("Home", "Home", FormMethod.Post))
{
#Html.DropDownListFor(model => model.SelectModel, Model.ModelItems)
<input type="submit" value="Go" />
}
So this is supposed to send Model to my controller.
But when i check the content of the passed Model in the controller, everything is NULL which isn't supposed to be because when i debug the view and check for the content of ModelItems, everything in the ModelItems is there.
Here is when i check the content of the passed Model
public ActionResult Home(Model model) <<<<<<<<<< Content == NULL
{
return View();
}
A <select> element on posts back a single value. Html has no concept of what your c# Model class is so you cannot bind to a complex object. You need to bind to the ModelId property of Model. Your view model should be
public class ModelVM
{
[Display(Name = "Model")]
public int SelectedModel { get; set; }
public SelectList ModelItems { get; set ;}
}
and in the controller
public ActionResult Index()
{
ModelVM modelVM = new ModelVM()
{
ModelItems = new SelectList(manager.GetAllModels(), "ModelId", "Name")
// SelectedModel = ? if you want to preselect an item
};
return View(modelVM);
}
and in the view
#Html.LabelFor(m => m.SelectedModel)
#Html.DropDownListFor(m => m.SelectedModel, Model.ModelItems)
and in the post method your model will be correctly bound with the ID of the selected model
Trying passing in type ModelVM to the Home action as that is the type being passed to Index view.
Instead of model.SelectModel in the drop-down declaration, you only need an int ID to capture which ID is selected.

MVC4 model binding and int/decimal overflow

Let's say I created a model with a property as int? type.
public class MyModel
{
[Range(-100, 100, ErrorMessage="Too large")]
public int? MyValue { get; set; }
}
In the view I use it for a text box in the form to post back to server.
#using (Html.BeginForm())
{
<p>Enter some value</p>
<div>#Html.TextBoxFor(m => m.MyValue)</div>
<div>#Html.ValidationMessageFor(m => m.MyValue)</div>
<input type="submit" value="Submit" />
}
Here is the controller code
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyModel();
return View(model);
}
[HttpPost]
public ActionResult Index(MyModel model)
{
return View(model);
}
}
Now if I enter an extremely large number in the text box, e.g 111111111111111111111111111111111111111111111111111111111111111111111111111111, which is for sure too large for an integer data type. On post back, got message The value '111111111111111111111111111111111111111111111111111111111111111111111111111111' is invalid.
But I have no way to use the error message (localization and so on) I defined in my model.
using System.ComponentModel.DataAnnotations;
public class MyModel
{
[Range(int.MinValue, int.MaxValue)]
public int? MyValue {get; set; }
}
That should do the trick.

Bootstrap Mvc.Grid for .NET MVC not accepting complex model

I am building a small Asp.NET MVC web application for document management system where I need to keep track of all the changes that happened with files and folders in jsTree (jQuery implementation of a tree control).
I have found Mvc.GRID Bootstrap control that enables (very easily) a grid representation of data. Let me describe what I did:
This is a model that partial view uses - List<List<HistoryVM>> and HistoryVM looks like this:
public class HistoryViewModel
{
[Display(Name="Name")]
string ItemName { get; set; }
[Display(Name="Original Path")]
public string ItemPath { get; set; }
[Display(Name="Type")]
public string ItemType { get; set; }
[Display(Name="Author")]
public string EventAuthorName { get; set; }
[Display(Name="Comment")]
public string EventActionDesc { get; set; }
[Display(Name="Timestamp")]
public DateTime DateOfEvent { get; set; }
[Display(Name="Action Type")]
public string ActionType { get; set; }
}
Controller looks like this:
[HttpGet]
public ActionResult ShowHistory(string path)
{
OperationService operations = new OperationService();
var historyRecord = operations.FindItemHistory(path);
if (historyRecord != null & historyRecord.Count() > 0)
{
return PartialView("../Shared/Partial/ShowHistory", historyRecord);
}
else
{
return PartialView("../Shared/Partial/ShowHistoryNoHistory");
}
}
And finally this is the view:
#model List<List<LaneWebApp.Models.HistoryViewModel>>
#using GridMvc.Html
#Html.AntiForgeryToken()
<div>
#Html.Grid(Model).Columns(c => {
c.Add(x => x.ElementAt(0).ItemType);
c.Add(x => x.ElementAt(0).ItemName);
c.Add(x => x.ElementAt(0).ItemPath);
c.Add(x => x.ElementAt(0).EventAuthorName);
c.Add(x => x.ElementAt(0).DateOfEvent.ToString());
c.Add(x => x.ElementAt(0).EventActionDesc);
})
</div>
Which gives me only the first element of each list. But I would like to have all history records, not just the first one.
How can I render this List of List in Grid.MVC?
It looks like current version of Bootstrap Grid.MVC does not support complex models - take a look at the official site.
So, I had to come up with my own view and sorting.

"inline" editing in a mvc 4 list of objects

I have a strange problem and I don't know if this is actually possible.
What I want is, to be able to list all the values from my model and and edit them directly in the list.
Here's what I have:
Model Linker:
public class StoreLinkerModel
{
//public Guid? id { get; set; }
public IEnumerable<Stores> StoresAndOpeninghours { get; set; }
}
public class Stores
{
public long ID { get; set; }
public string StoreName { get; set; }
public string Address { get; set; }
public string Zip { get; set; }
public string City { get; set; }
}
My Controller:
public ActionResult Overview()
{
var model = new StoreLinkerModel
{
StoresAndOpeninghours = new[]
{
new Stores()
{
ID = 0,
Address = "Enghavevej 70"
},
new Stores()
{
ID=1,
Address = "Løngangsgade 30"
},
}
};
return View(model);
}
[HttpPost]
public ActionResult Overview(StoreLinkerModel model)
{
if (ModelState.IsValid)
{
var x = "go go go";
}
return RedirectToAction("Overview");
}
My overview.aspx page:
#model streetoffrs.web.Models.StoreLinkerModel
#{
ViewBag.Title = "Overview";
Layout = "~/Views/Shared/_dashboard.cshtml";
}
#Html.EditorFor(x => x.StoresAndOpeninghours)
and my EditorTemplate stores.aspx
#model streetoffrs.web.Models.Stores
#using (Html.BeginForm("Overview", "Dashboard", FormMethod.Post, new { name = "id" + #Html.DisplayFor(m => m.ID) }))
{
#Html.EditorFor(x => x.Address)
<input type="submit" class="left btn btn-primary" value="Ret butiksdata">
}
<br />
The list is being generated as it should, and when I hit the first button at the first editorfor it will post the model to my controller, but when I push the 2nd button, the model is null, but the first button still works!
Is this possible at all, if yes what am I missing, if not, tell me how I can accomplish this.
thanks in advance!
you need edit post action like this:
[HttpPost]
public ActionResult Overview(StoreLinkerModel model)
{
if (ModelState.IsValid)
{
var x = "go go go";
}
return View(model);
}
the RedirectToAction will be go to the first Overview Action,so you will be lost the data.