passing single model twice or thrice to contoller - asp.net-mvc-4

I am new to asp.net MVC-4 and stuck up while retrieving data from view to controller in case of render single partial view twice on company/create.cshtml
My complex model is as follow.
public partial class Company
{
public int CCode { get; set; }
public string CName { get; set; }
public string Addr1 { get; set; }
public string Addr2 { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string EmailID { get; set; }
public string Remarks { get; set; }
public CompanyContacts Contacts { get; set; }
public partial class CompanyContacts
{
public int refCCode_Company { get; set; }
public int SrNo { get; set; }
public string ContactPerson { get; set; }
public string Designation { get; set; }
public string Contact1 { get; set; }
public string Contact2 { get; set; }
public string EmailID { get; set; }
public string IsActive { get; set; }
}
}
where in the CompanyContact is partial view rendered twice in company/create.cshtml page.
"#model ProjectName.Models.Company" so that i can bind HTML control as follow. #HTML.TextBoxFor(model >= model.CompanyContact)
<div class="tab-pane fade" id="contacts">
<div class="col-md-6">
<p>
#Html.Partial("_LedgerContactsPartial")
</p>
</div>
<div class="col-md-6">
<p>
#Html.Partial("_LedgerContactsPartial")
</p>
</div>
</div>
while save the data, how do i pass two contact person details to controller.
Thanks in Adv.

You need to pass list of contact person details to controller. to achieve this you could follow naming convention for input fields that the default ModelBinder expects to bind to a list.
This article by Phill Hack shows Model Binding To A List.
And take look to this question How to pass IEnumerable list to controller in MVC including checkbox state.

Related

Get lastest record from section using mvc5

I want to show in my home page: All section (all link category and one lastest news record in this section).
Please help me to complete my code.
Thank you so much.
My DbContext class:
public partial class xxDbContext : DbContext
{
public xxDbContext()
: base("name=xxDbConnection") { }
public virtual DbSet<Category> Categories { get; set; }
public virtual DbSet<Section> Sections { get; set; }
public virtual DbSet<News> News { get; set; }
}
public partial class Section
{
public int Id { get; set; }
public string Name { get; set; }
public virtual List<Category> Categories { get; set; }
}
public partial class Category
{
public int Id { get; set; }
public int SectionId { get; set; }
public string Name { get; set; }
public virtual Section Section { get; set; }
}
public partial class News
{
public int Id { get; set; }
public int CateId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
}
My controllers
public ActionResult NewsInSec()
{
var model = db.Sections.Where(m => m.Publish).ToList();
return PartialView("NewsInSec", model);
}
My view
#model IEnumerable<xx.Models.Section>
<div>
#foreach (var sect in Model)
{
<ol class="breadcrumb">
<li>#sect.Name</li>
#foreach (var cate in sect.Categories)
{
<li>#cate.Name</li>
}
</ol>
**foreach (var item in sect.Categories.SelectMany(c => c.News).Where(c => c.Publish).OrderByDescending(c => c.CreateDate).Take(4).ToList())
{
<div>
#* News title*#
<h4>#item.Title</h4>
<img src="~/img/news/#item.Image" />
#*Content of lastest news*#
<p>#item.NewsContent</p>
<p>#item.Title</p>
</div>
}**
}
Finally, i want to show section, cate, news as my attached photo.
Please help me to see and fix my code above one more time? Thanks and thanks so much.
You can add navigation property in Category for easy access to News.
public partial class Category
{
public int Id { get; set; }
public int SectionId { get; set; }
...
public virtual List<News> News { get; set; }
}
And select last news for section:
#foreach (var cate in sect.SelectMany(s=>s.Categories.SelectMany(c=>c.News))
.OrderByDescending(n=>n.ID).Take(5))
{
<div>
// Title of lastest news
<h3></h3>
<img src="~/img/...." />
// Content of lastest news
<p></p>
</div>
}
Note: more correct way find last news in your Controller and include result in ViewModel, Like that:
public class SomeViewModel
{
public IEnumerable<Section> Sections {get;set;}
public IEnumerable<News> LastNews{get;set;}
}
Fill this model in controller and pass in view.

#Html.LisboxFor Model Binding for multiple items

My Class is
public partial class Team
{
public int TeamId { get; set; }
public string TeamName { get; set; }
public string TeamDescription { get; set; }
public virtual IList<Trials> Trials { get; set; }
}
Trials is anothetr calss
public partial class Trials
{
public int TrialID { get; set; }
public string Name { get; set; }
public int TrialTyp_RefID { get; set; }
public bool isChk { get; set; }
public virtual ICollection<Team> Team { get; set; }
}
in my view I amn trying to bind the ListBoxFor with Trials inseide the team
#model Trials.Classes.Team
<td colspan="2">
#Html.ListBoxFor(model=> model.Trials,
new SelectList(ViewBag.trials,"TrialID", "Name"),
new { #class = "chosen-select", data_placeholder = "Select Trials...", style = "width:500px;", tabindex = "4" }
)
</td>
I cant get any value for Trials calss in the controller ..It shows null but I select multi values from listbox
A multiple select only posts back an array of primitive values. It does not post back a collection of complex objects.
You need a view model with a property to bind the selected Trials
public class TeamVM
{
public int TeamId { get; set; }
....
public int[] SelectedTrials { get; set; }
public SelectList Trials { get; set; } // Assign this in your controller rather than using ViewBag
}
then in you view
#Html.ListBoxFor(m => m.SelectedTrials, Model.Trials)
When you post back, Team.SelectedTrials will contain and array of the selected TrialID values.
I changed the Team class as
public partial class Team
{
public int TeamId { get; set; }
public string TeamName { get; set; }
public string TeamDescription { get; set; }
public virtual IList<Trials> Trials { get; set;
public int[] AuthorisedTrials { get; set; }
}
and in View
#model Trials.Classes.Team
<td colspan="2">
#Html.ListBoxFor(model=> model.AuthorisedTrials ,
new SelectList(ViewBag.trials,"TrialID", "Name"),
new { #class = "chosen-select", data_placeholder = "Select Trials...", style = "width:500px;", tabindex = "4" }
)
</td>
and in my controller I was able to get the Vlaues for Selected Trials

Why viewmodel modelstate validates navigation property of an entity?

I have a problem with simple validation during controller Create action for entity ARTICLE. I am using EF 4 database first. Entity ARTICLE is used as foreign key in entity ACTION(ACTION.ARTICLE_id). That's why code generation tool add navigation property to entity ARTICLE, even it does not make not much sense. Each time I update entities the clasess gets to form below(ARTICLE). I checked all foreign key many times again. I really dont know what to do with this error to make clean soluton, not just clearing error in controller action. Everything - even view are scaffolded.
Action:
[HttpPost]
[Authorize(Roles = "ARTICLE_ADMIN")]
public ActionResult Edit(ARTICLE article)
{
if (ModelState.IsValid)
{
article.date_modified = DateTime.Now;
string newimage = this.Request.Form["preview_image_filename"];
string oldimage = this.Request.Form["original_image_filename"];
if (newimage.NotNullOrEmpty())
{
article.preview_image = newimage;
}
else
{
article.preview_image = oldimage;
}
db.Entry(article).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
article.date_modified = DateTime.Now;
ViewBag.ARTICLE_CATEGORY_id = new SelectList(db.ARTICLE_CATEGORY, "ARTICLE_CATEGORY_id", "description", article.ARTICLE_CATEGORY_id);
ViewBag.ARTICLE_STATUS_id = new SelectList(db.ARTICLE_STATUS, "ARTICLE_STATUS_id", "description", article.ARTICLE_STATUS_id);
ViewBag.WEB_USER_id = new SelectList(db.WEB_USER, "WEB_USER_id", "login", article.WEB_USER_id);
return View(article);
}
I am using this entity model generated via code generation tool with added annotations in metadata class, it cant be more simple
public partial class ARTICLE
{
public ARTICLE()
{
this.PROGRAM_WEEK_DAY_ITEM = new HashSet<PROGRAM_WEEK_DAY_ITEM>();
this.STORAGE = new HashSet<STORAGE>();
this.SHOW = new HashSet<SHOW>();
this.ACTION = new HashSet<ACTION>();
}
public int ARTICLE_id { get; set; }
public System.DateTime date_created { get; set; }
public Nullable<System.DateTime> date_modified { get; set; }
public string title { get; set; }
public string html { get; set; }
public int WEB_USER_id { get; set; }
public int ARTICLE_STATUS_id { get; set; }
public int ARTICLE_CATEGORY_id { get; set; }
public Nullable<System.DateTime> date_published { get; set; }
public string preview_image { get; set; }
//code generation tool added those navigation props
public virtual ARTICLE_CATEGORY ARTICLE_CATEGORY { get; set; }
public virtual ARTICLE_STATUS ARTICLE_STATUS { get; set; }
public virtual WEB_USER WEB_USER { get; set; }
public virtual ICollection<PROGRAM_WEEK_DAY_ITEM> PROGRAM_WEEK_DAY_ITEM { get; set; }
public virtual ICollection<STORAGE> STORAGE { get; set; }
public virtual ICollection<SHOW> SHOW { get; set; }
//this one causes trouble I think, but no clue why
public virtual ICollection<ACTION> ACTION { get; set; }
}
metadata class - just display names and formats:
public class ARTICLE_Metadata
{
[Key]
public int ARTICLE_id { get; set; }
[Display(Name="Vytvořeno")]
public System.DateTime date_created { get; set; }
[Display(Name = "Změněno")]
public Nullable<System.DateTime> date_modified { get; set; }
[Display(Name = "Publikováno")]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
public Nullable<System.DateTime> date_published { get; set; }
[Display(Name = "Titulek článku")]
public string title { get; set; }
[Display(Name = "Obsah článku")]
[UIHint("tinymce_full"), AllowHtml]
public string html { get; set; }
[Display(Name = "Vytvořil")]
public int WEB_USER_id { get; set; }
[Display(Name = "Status")]
public int ARTICLE_STATUS_id { get; set; }
[Display(Name = "Kategorie")]
public int ARTICLE_CATEGORY_id { get; set; }
[Display(Name = "Náhledový obrázek")]
public string preview_image { get; set; }
}
and finally form in razor view:
#using (Html.BeginForm("Create", "Articles", FormMethod.Post, new { #class = "base-form" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Nový článek</legend>
#Html.DatePickerFor(model => model.date_published, false)
#Html.HiddenFor(model => model.WEB_USER_id)
<p class="editor-label">
#Html.LabelFor(model => model.ARTICLE_STATUS_id)
#Html.DropDownList("ARTICLE_STATUS_id")
#Html.ValidationMessageFor(model => model.ARTICLE_STATUS_id)
</p>
<p class="editor-label">
#Html.LabelFor(model => model.ARTICLE_CATEGORY_id)
#Html.DropDownList("ARTICLE_CATEGORY_id")
#Html.ValidationMessageFor(model => model.ARTICLE_CATEGORY_id)
</p>
<p class="editor-label">
#Html.LabelFor(model => model.title)
#Html.EditorFor(model => model.title)
#Html.ValidationMessageFor(model => model.title)
</p>
<div class="html-editor">
#Html.EditorFor(model => model.html)
</div>
<p>
<input type="submit" value="Vytvořit" class="submit" />
</p>
</fieldset>
}
When model validates and comes to controller action, ModelState.IsValid == false, ModelState claims error on property ACTION which is not even present in the table and not supposed to be there, it is navigation property.
Error has an exeption: The parameter conversion from type 'System.String' to type 'namespace.ACTION' failed because no type converter can convert between these types.
I tried to attach debugger view image but this web did not allowed it to me. I have other entities managed via controllers and view the same way - about 30 where this does not happen.
How can I get rid of this problem without creating extra model with the same properties but without navigation ones? Or just prevent this navigation property to be included to validation. Or it is a new microsoft nonsense feature?
Some times these weird errors in db-first comes from that the name of a navigation property in an entity, is same as the name of another entity. I myself experienced these problems sometimes, and I don't know exactly what is the reason.
Anyway, renaming that navigation property must get you rid of that weird error...

System.Collections.Generic.IEnumerable<MyBlogSite.Models.BlogPost>' does not contain a definition for 'Categories'

Here is my BlogPost Model class:
public class BlogPost
{
public int Id { get; set; }
public string Title { get; set; }
[AllowHtml]
public string ShortDescription { get; set; }
[AllowHtml]
public string PostBody { get; set; }
public string Meta { get; set; }
public string UrlSlug { get; set; }
public DateTime PostedOn { get; set; }
public DateTime? Modified { get; set; }
public virtual ICollection<BlogPostCategory> Categories { get; set; }
public virtual ICollection<BlogPostTag> Tags { get; set; }
}
Here is my BlogPostCategory Model class:
public class BlogPostCategory
{
public int Id { get; set; }
public string Name { get; set; }
public string UrlSlug { get; set; }
public string Description { get; set; }
// Decared virtual because the data must be returned from another table.
public virtual ICollection<BlogPost> BlogPosts { get; set; }
}
Each class belongs to a separate Controller/View.
Finally, here is the top port of the Index View for Blog:
#model IEnumerable<MyBlogSite.Models.BlogPost>
#{
ViewBag.Title = "Index";
}
#Html.RenderPartial("~/Views/Category/_Categories.cshtml", Model.Categories );
<p>
#Html.ActionLink("New Blog Post", "Create")
</p>
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.Title)
</th>
....
In the View where Model.Categories is being passed in is where I am getting the exception from the title of this post. It seems to me that I have defined Categories within the BlogPost Model. What am I doing wrong?
The Model on your Razor page is an IEnumerable<MyBlogSite.Models.BlogPost>. It seems you're trying to display the information about each of the items in your collection. If so, then you can loop through them or create a display/editor template and use #Html.DisplayFor(x => x) or #Html.EditorFor(x => x), respectively.
#foreach(var post in Model) {
<p>Do stuff here with the local "post" variable.</p>
}
Here's a link to Scott Gu's blog talking about the #model directive in Razor views.

Try to access a property of parent viewmodel in displaytemplate

I'm trying to build an asp.net mvc 4 application that makes use of partial views and display/editortemplates and Kendo ui.
I have a viewmodel for a specific page:
public class Plant {
public Guid PlantId{ get; set; }
public string Name { get; set; }
public string Description { get; set; }
public ICollection<Leaf> Leafs{ get; set; }
public ICollection<Flower> Flowers{ get; set; }
public ICollection<Bug> Bugs{ get; set; }
}
And as well Leaf, Flower as Bug have their own properties.
By example:
public class Leaf {
public Guid LeafId{ get; set; }
public string Name { get; set; }
public string Documentation { get; set; }
public string Description { get; set; }
}
I'm making use of partialviews in my view so it makes it more easy to update them with ajax.
My normal view : PlantDetail.cshtml
#model Plant
<table>
<tr>
<td>
<h2>#Html.Label(Resources.PlantDetailTitle)</h2>
</td>
<td>
#Html.HiddenFor(m => m.PlantId)
#Html.DisplayFor(m => m.Name)
</td>
</tr>
<tr>
<td>#Html.LabelFor(m => m.Description)
</td>
<td>
#Html.DisplayFor(m => m.Description)
</td>
</tr>
</table>
#{Html.RenderPartial("_flowers", Model);}
#{Html.RenderPartial("_leafs", Model);}
In my partial view "_leafs" (as well as in "_flowers" I have a serie of buttons that invoke an action that needs the LeafId and the PlantId:
The partial view "_leafs":
#model List<Leaf>
#for (int i = 0; i < Model.Count(); i++ )
{
#(Html.DisplayFor(m => m[i]))
}
My displayTemplate "Leaf.cshtml":
#model Leaf
#Html.HiddenFor(m =>m.LeafId)
<a class='k-button k-button-icontext' href=#Url.Action("InitiateLeaf", "Plant") +"?
leafId=#Model.LeafId&plantId=#=PlantId#">#Model.Name</a>
Now my problem is that I can't seem to access the PlantId of my Parent Viewmodel in my displaytemplate. (And I have the same problem in each of my displaytemplates..)
I've allready tried it with routevalues in my url.action and I know that I can eventually access the PlantId in javascript, but is there any (mvc) way to keep using displaytemplates and don't duplicate my plantId as a property of my child Leaf viewmodel?
I've allready tried to acces my parentviewcontext with something like
"#HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString()" in my displaytemplate, but don't seem the find the value of my PlantId (if it is even stored there..).
Anyone else still has some suggestions?
One option as you mentioned, is to use jquery to access the parent PlantId. If you have a requirement to access your parent's properties, its better to design your view models similar to how Entity framework recommends us to create model classes.
public class Plant {
public Guid PlantId{ get; set; }
public string Name { get; set; }
public string Description { get; set; }
public ICollection<Leaf> Leafs{ get; set; }
public ICollection<Flower> Flowers{ get; set; }
public ICollection<Bug> Bugs{ get; set; }
}
So your Leaf class should also have a navigational property to go back to Plant.
public class Leaf {
public Guid LeafId{ get; set; }
public string Name { get; set; }
public string Documentation { get; set; }
public string Description { get; set; }
public virtual Plant Plant { get; set; }
public Guid PlantId { get; set; }
}
Make sure you populate the Plant property and PlantId when you create the ViewModel. Hope this helps