How do I populate a menu by using recursive loop? - asp.net-mvc

Below are the info.
No idea how to loop the SubNav item in the View. (Ref: Loop Through Multi-Level Dynamic Menus in Asp.Net MVC)
Controller
[ChildActionOnly]
public PartialViewResult LoadNav()
{
var db = new NavDb();
List<Nav> NavCol = db.Navs.ToList<Nav>();
var navObj = CreateNavVM(0, NavCol);
return PartialView("_PVTopNav", navObj);
}
public IEnumerable<NavViewModel> CreateNavVM(int pParentId, List<Nav> pNavCol)
{
return from m in pNavCol
orderby m.DisplaySeq
where m.ParentMenuId == pParentId
select new NavViewModel()
{
MenuId = m.MenuId,
Name = m.Name,
HtmlTitle = m.HtmlTitle,
Url = m.Url,
DisplaySeq = m.DisplaySeq,
SubNav = (IEnumerator<NavViewModel>)CreateNavVM(m.MenuId, pNavCol)
};
}
ViewModel
public class NavViewModel
{
public int MenuId { get; set; }
public int ParentMenuId { get; set; }
public string Name { get; set; }
public string HtmlTitle { get; set; }
public string Url { get; set; }
public int DisplaySeq { get; set; }
public IEnumerator<NavViewModel> SubNav { get; set; }
}
Model
public class Nav
{
[Key]
public int MenuId { get; set; }
public int ParentMenuId { get; set; }
public string Name { get; set; }
public string HtmlTitle { get; set; }
public string Url { get; set; }
public int DisplaySeq { get; set; }
}
View
#model IEnumerable<yetpweb.ViewModels.NavViewModel>
#foreach (var m in Model) {
<div class="ui simple dropdown item">
#m.Name
<div class="menu">
<a class="item" href="#">Link Item</a>
<a class="item" href="#">Link Item</a>
<div class="item">
<i class="dropdown icon"></i>
Sub Menu
<div class="menu">
<a class="item" href="#">Link Item</a>
<a class="item" href="#">Link Item</a>
</div>
</div>
<a class="item" href="#">Link Item</a>
</div>
</div>
}

You can just start another razor foreach statement. In your code this would result in:
#foreach (var m in Model) {
<div class="ui simple dropdown item">
#m.Name
<div class="menu">
<a class="item" href="#">Link Item</a>
<a class="item" href="#">Link Item</a>
<div class="item">
<i class="dropdown icon"></i>
#foreach(var sub in m.SubNav) {
<div class="menu">
<a class="item" href="#">Link Item</a>
<a class="item" href="#">Link Item</a>
</div>
}
</div>
<a class="item" href="#">Link Item</a>
</div>
</div>
}

Related

Creating a comment-like box in ASP.NET Core

I'm trying to create a comment and like box like the one shown in this tutorial what are the main changes I need to make in order to make it work with ASP.NET Core 3.1
https://www.c-sharpcorner.com/blogs/how-to-create-a-comment-box-session-as-like-facebook-comment-in-asp-net
To create a Facebook-like comment box in ASP.NET Coreļ¼Œ I do a demo to make it, referring to official documentation to configure database:https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/adding-model?view=aspnetcore-5.0&tabs=visual-studio
1.To Create the comment box, we need to create User, Reply, Comment models to add some tables ,and add some ViewModels.
User.cs:
public class User
{
[Key]
public int Id { get; set; }
[Required]
public string UserName { get; set; }
[Required]
public string Password { get; set; }
[Required]
public string Email { get; set; }
public string ImageUrl { get; set; }
public DateTime? CreateOn { get; set; }
}
Reply.cs:
public class Reply
{
[Key]
public int Id { get; set; }
[Required]
public string Text { get; set; }
public DateTime? CreateOn { get; set; }
public int UserId { get; set; }
[ForeignKey("UserId")]
public virtual User User { get; set; }
public int CommentId { get; set; }
[ForeignKey("CommentId")]
public virtual Comment Comment{get;set;}
}
Comment.cs:
public class Comment
{
[Key]
public int Id { get; set; }
[Required]
public string Text { get; set; }
public DateTime? CreateOn { get; set; }
public int UserId { get; set; }
[ForeignKey("UserId")]
public virtual User User { get; set; }
public ICollection<Reply> Replies { get; set; }
public ICollection<User> Users { get; set; }
}
LoginVM.cs:
public class LoginVM
{
[Required]
[Key]
public string UserName { get; set; }
[Required]
public string Password { get; set; }
}
RegisterVM.cs:
public class RegisterVM
{
[Required]
public string UserName { get; set; }
[Required]
public string Password { get; set; }
[Compare("Password")]
public string ConfirmPassword { get; set; }
[Required]
public string Email { get; set; }
}
ReplyVM.cs:
public class ReplyVM
{
public string Reply { get; set; }
public int CID { get; set; }
}
Installs the EF Core package
From the Tools menu, select NuGet Package Manager > Manage NuGet Packages for solution.
[Note]My core3.1 installed 3.1.21 version
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Tools
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.SqlServer.Design
Microsoft.EntityFrameworkCore.Proxies
Microsoft.Extensions.Configuration.JSON
creates a database context class: Models/ApplicationDbContext.cs
public class ApplicationDbContext: DbContext
{
public ApplicationDbContext(DbContextOptions options) :base(options)
{
}
public DbSet<User> Users { get; set; }
public DbSet<Comment> Comments { get; set; }
public DbSet<Reply> Replies { get; set; }
public DbSet<commentbox.ViewModels.LoginVM> LoginVM { get; set; }
}
4.Add codes in Startup.ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
services.AddSession();
services.AddControllersWithViews();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("ApplicationDbContext")));
}
5.Add app.UseSession(); in Startup.Configure
6.Add a connection string to the appsettings.json file:
"ConnectionStrings": {
"ApplicationDbContext": "Server=(localdb)\\mssqllocaldb;Database=ApplicationDbContext-1;Trusted_Connection=True;MultipleActiveResultSets=true"}
7.In the Package Manager Console (PMC), enter the following commands separately:
Add-Migration InitialCreate
Update-Database
8.Add HomeController to set userId=0 when people first Login without register, add AccountController to manage user login or not, add ChatRoomController to manage user post comments or reply.
HomeController.cs:
public class HomeController : Controller
{ ....
public IActionResult Index()
{
ISession session = HttpContext.Session;
session.SetInt32("UserId", 0);
return View();
}
...
}
AccountController.cs:
public class AccountController : Controller
{
private readonly ApplicationDbContext db;
public AccountController(ApplicationDbContext context)
{
db = context;
}
//GET:Account/Register
[HttpGet]
public IActionResult Register()
{
return View();
}
//GET:Account/Register
[HttpPost]
public IActionResult Register(RegisterVM obj)
{
bool UserExistis=db.Users.Any(x=>x.UserName==obj.UserName);
if(UserExistis)
{
ViewBag.UserNameMessage = "This UserName is already in use, try another";
return View();
}
bool EmailExistis = db.Users.Any(y => y.Email == obj.Email);
if (EmailExistis)
{
ViewBag.EmailMessage = "This Email is already in use, try another";
return View();
}
//if username and email is unique, then we save or register the user
User u = new User();
u.UserName = obj.UserName;
u.Password = obj.Password;
u.Email = obj.Email;
u.ImageUrl = "";
u.CreateOn = DateTime.Now;
db.Users.Add(u);
db.SaveChanges();
return RedirectToAction("Index","ChatRoom");
}
//GET:Account/Login
[HttpGet]
public IActionResult Login()
{
return View();
}
//GET:Account/Login
[HttpPost]
public IActionResult Login(LoginVM obj)
{
bool existis = db.Users.Any(u => u.UserName == obj.UserName&&u.Password==obj.Password);
if(existis)
{
ISession session = HttpContext.Session;
session.SetInt32("UserId", db.Users.Single(x => x.UserName == obj.UserName).Id);
return RedirectToAction("Index","ChatRoom");
}
//if invalid credentials
ViewBag.Message = "Invalid Credentials!";
return View();
}
}
ChatRoomController.cs:
public class ChatRoomController: Controller
{
private readonly ApplicationDbContext db;
public ChatRoomController(ApplicationDbContext context)
{
db = context;
}
public IActionResult Index()
{
var comments = db.Comments.Include(x => x.Replies).ThenInclude(x=>x.User).OrderByDescending(x => x.CreateOn)
.ToList();
return View(comments);
}
//Post:ChatRoom/PostReply
[HttpPost]
public ActionResult PostReply(ReplyVM obj)
{
ISession session = HttpContext.Session;
int userId =(int)session.GetInt32("UserId");
if (userId==0)
{
return RedirectToAction("Login", "Account");
}
Reply r = new Reply();
r.Text = obj.Reply;
r.CommentId = obj.CID;
r.UserId =userId;
r.CreateOn = DateTime.Now;
db.Replies.Add(r);
db.SaveChanges();
return RedirectToAction("Index");
}
//Post:ChatRoom/PostComment
[HttpPost]
public ActionResult PostComment(string CommentText)
{
ISession session = HttpContext.Session;
int userId = (int)session.GetInt32("UserId");
if (userId == 0)
{
return RedirectToAction("Login", "Account");
}
Comment c = new Comment();
c.Text = CommentText;
c.CreateOn = DateTime.Now;
c.UserId = userId;
db.Comments.Add(c);
db.SaveChanges();
return RedirectToAction("Index");
}
}
9.Add views: Login.cshtml(for Login action in AccountController), Register.cshtml(for Register action in AccountController), index.cshtml(for Index action in ChatRoomController).
Login.cshtml:
#model commentbox.ViewModels.LoginVM
#{
ViewData["Title"] = "Login";
}
<h1>Login</h1>
#Html.AntiForgeryToken()
<div class="row">
<div class="col-md-4">
<form asp-action="Login">
<h4 class="text-danger">#ViewBag.Message</h4>
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="UserName" class="control-label"></label>
<input asp-for="UserName" class="form-control" />
<span asp-validation-for="UserName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Password" class="control-label"></label>
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-success" />
</div>
</form>
</div>
</div>
Register.cshtml:
#model commentbox.ViewModels.RegisterVM
#{
ViewData["Title"] = "Register";
}
<h1 class="text-success">Register User</h1>
<div class="row">
<div class="col-md-4">
<form asp-action="Register">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="UserName" class="control-label"></label>
<input asp-for="UserName" class="form-control" />
<span asp-validation-for="UserName" class="text-danger"></span>
<p class="text-danger">#ViewBag.UserNameMessage </p>
</div>
<div class="form-group">
<label asp-for="Password" class="control-label"></label>
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ConfirmPassword" class="control-label"></label>
<input asp-for="ConfirmPassword" class="form-control" />
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Email" class="control-label"></label>
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
<p class="text-danger">#ViewBag.EmailMessage </p>
</div>
<div class="form-group">
<input type="submit" value="Register" class="btn btn-primary" style="border-radius:20px"/>
</div>
</form>
</div>
</div>
Index.cshtml:
#model IEnumerable<commentbox.Models.Comment>
#{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<h2 class="text-success text-center"> someone's post or some other things</h2>
#using (Html.BeginForm("PostComment", "ChatRoom", FormMethod.Post))
{
<input type="text" name="CommentText" placeholder="Type new comment..."
style="width:700px; height:60px; font-size:20px; margin-top:10px" />
<br />
<input type="submit" value="Post Comment" class="btn btn-success "
style="margin-top: 10px;margin-bottom: 10px " />
}
<table class="table text-center">
<tbody>
#foreach (var comment in Model)
{
<tr style="border:1px solid black;">
<td>
<span style="margin-right:15px;font-size:16px;color:green">
#Html.DisplayFor(modelItem => comment.User.UserName)
</span>
<span style="font-size:20px">
#Html.DisplayFor(modelItem => comment.Text)
</span>
<span style="margin-left:10px">
#Html.DisplayFor(modelItem => comment.CreateOn)
</span>
#foreach (var reply in comment.Replies)
{
<br />
<span style="margin-right:15px;font-size:16px;color:blue">
#Html.DisplayFor(modelItem => reply.User.UserName)
</span>
<span style="font-size:19px">
#reply.Text
</span>
<span style="margin-left:10px">
#reply.CreateOn
</span>
}
<br />
#using (Html.BeginForm("PostReply", "ChatRoom", FormMethod.Post))
{<input type="text" name="Reply" placeholder="Type reply..."
style="width:100%; height:60px; font-size:20px; margin-top:10px" />
<br />
<input type="hidden" name="CID" value="#comment.Id" />
<input type="submit" value="Post Reply" class="btn btn-success" style="margin-top :10px" />
}
</td>
</tr>
}
</tbody>
</table>
10.Add link in _Layout.cshtml.
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Account" asp-action="Register">Register</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Account" asp-action="Login">Login</a>
</li>

how to send dropdownlist value in the begin form to the controller

i want to pass the selected dropdown list item value to the controller , im able to send the datepicker values but not dropdownlist item values.
view
#using (Html.BeginForm())
{
<div class="btn-group">
<button type="button" class="btn btn-info ">Device Id</button>
<button type="button" class="btn btn-info dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="sr-only">Toggle Dropdown</span>
</button>
<div class="dropdown-menu">
#foreach (var item in Model.OrderBy(x=>x.DeviceId).Select(x => x.DeviceId).Distinct())
{
<a class="dropdown-item" href="#" id="deviceid_dropdown">#item</a>
}
</div>
<div class="col-md-1">
<input type="submit" id="btnSubmit" name="Submit" class="btn btn-success" value="Submit" />
</div>
</div>
}
controller
public ActionResult Reports(DateTime? fromDate, DateTime? toDate, string deviceid_dropdown)
{
}
Model
#model List<SmartPond.Models.SmartPondViewModel>
viewmodel
public class SmartPondViewModel
{
public string Imie { get; set; }
public int DeviceId { get; set; }
public string pH { get; set; }
public string DissolvedOxygen { get; set; }
public string Temperature { get; set; }
public DateTime Timestamp { get; set; }
}

Comments with replies won't show properly (ASP.NET MVC)

(Reposted question, since the other one was put on hold and then edited but not reopened)
I have a problem with showing comment replies in my comment section on my website. I have made it so there is a Original Comment and that comment can have subcomment (replies) and the way I have set up my code it does work, but if there are 2 original comments and 1 reply on in one section, then it shows the reply og both of them, even though I've coded it to only show on a specific original comment.
Comment model:
namespace ComicbookWebpage.Models
{
public class ComicComment
{
public int Id { get; set; }
public string Comment { get; set; }
public DateTime Posted { get; set; }
public string UserId { get; set; }
public virtual ApplicationUser User { get; set; }
public int ComicId { get; set; }
public Comic Comic { get; set; }
public List<SubComicComment> SubComicComments { get; set; }
}
}
SubComment model (reply):
namespace ComicbookWebpage.Models
{
public class SubComicComment
{
public int Id { get; set; }
public string CommentText { get; set; }
public DateTime Posted { get; set; }
public SubComicComment() {
Posted = DateTime.Now;
}
public string UserId { get; set; }
public ApplicationUser User { get; set; }
public int ComicId { get; set; }
public Comic Comic { get; set; }
public int OriginalCommentId { get; set; }
public ComicComment ComicComment { get; set; }
}
}
Here's my viewmodel I use for all my data (vm):
namespace ComicbookWebpage.Models.ViewModels
{
public class ComicVM
{
public Comic Comic { get; set; }
public Series Series { get; set; }
public List<ComicComment> ComicComments { get; set; }
public List<SubComicComment> SubComicComments { get; set; }
}
}
So as you can see there is an "OriginalCommentId" in my subcomments table, so that I can tell my subcomments what original comment they belong to, so they're only shown under that specific comment. But the problem is like I said above that it shows my subcomment under 2 different original comments on the same page, if the page has 2 original comments, here's an image:
(Image) Comments in view (Browser SS)
On the right side of every comment, you can see an ID, it's the ID that the comment has and you can clearly see that the ID 9 has a subcomment with ID 2, which is totally wrong according to my coding. Because I'm telling my list to render the data where the original comment id is the same as subcomment's OriginalCommentId, so they should both have ID 9, but the subcomment has ID 2 for some reason...
Here's the controller code (Look at vm.SubComicComments):
public ActionResult Comic(int id)
{
ComicVM vm = new ComicVM();
vm.Comic = db.Comics.Include(m => m.Series).Where(m => m.Id == id).FirstOrDefault();
vm.Series = db.Series.FirstOrDefault();
vm.ComicComments = db.ComicComments.Where(m => m.Comic.Id == id).ToList();
vm.SubComicComments = db.SubComicComments.Where(m => m.ComicId == id && m.ComicComment.Id == m.OriginalCommentId).ToList();
db.Users.ToList();
return View(vm);
}
And here's the view code:
#using Microsoft.AspNet.Identity
#using System.Data.Entity;
#model ComicbookWebpage.Models.ViewModels.ComicVM
#{
ViewBag.Title = #Model.Comic.Title;
}
<a class="btn btn-default" href="/Series/Details/#Model.Comic.SeriesId"><i class="glyphicon glyphicon-menu-left"></i> Back</a>
<hr />
<h5><b>Title:</b> #Model.Comic.Title</h5>
<h5><b>Series:</b> #Model.Comic.Series.Title</h5>
<h5><b>Pages:</b> #Model.Comic.PageAmount</h5>
<hr />
<h4><i class="glyphicon glyphicon-comment"></i> Leave a comment:</h4>
<br />
#if (User.Identity.IsAuthenticated)
{
<div class="col-sm-1">
<div class="thumbnail">
<img class="img-responsive user-photo" src="https://ssl.gstatic.com/accounts/ui/avatar_2x.png">
</div><!-- /thumbnail -->
</div><!-- /col-sm-1 -->
<div class="col-sm-5">
<form action="/Series/Comic/#Model.Comic.Id" method="post">
<input type="hidden" name="Posted" value="#DateTime.Now" />
<input type="hidden" name="UserId" value="#User.Identity.GetUserId()" required />
<input type="hidden" name="ComicId" value="#Model.Comic.Id" />
<textarea class="form-control form-text" type="text" name="Comment" placeholder="Type your comment..." required></textarea>
<br />
<button type="submit" class="btn bg-dark">Send</button>
</form>
</div><!-- /col-sm-5 -->
}
else
{
<h5>You have to be logged in to post a comment.</h5>
<p>Click here to login</p>
}
<div class="row">
<div class="col-md-12">
#if (Model.ComicComments.Count > 0)
{
<h4>(#Model.ComicComments.Count) Comments:</h4>
}
else
{
<h4>0 Comments:</h4>
<p>There are currently no comments posted on this comic book.</p>
}
</div>
</div>
#foreach (var Comment in Model.ComicComments.Where(m => m.ComicId == m.Comic.Id))
{
<div class="comments-container">
<ul id="comments-list" class="comments-list">
<li>
<div class="comment-main-level">
<!-- Avatar -->
<div class="comment-avatar"><img src="https://i9.photobucket.com/albums/a88/creaticode/avatar_1_zps8e1c80cd.jpg" alt=""></div>
<!-- Contenedor del Comentario -->
<div class="comment-box">
<div class="comment-head">
<h6 class="comment-name by-author">#Comment.User.UserName</h6>
<span>posted on #Comment.Posted.ToShortDateString()</span><i>ID: #Comment.Id</i>
</div>
<div class="comment-content">
#Comment.Comment
</div>
</div>
</div>
<!-- Respuestas de los comentarios -->
<ul class="comments-list reply-list">
#if (Model.SubComicComments.Count > 0)
{
foreach (var SubComment in Model.SubComicComments.Where(m => m.OriginalCommentId == m.ComicComment.Id))
{
<li>
<!-- Avatar -->
<div class="comment-avatar"><img src="https://i9.photobucket.com/albums/a88/creaticode/avatar_2_zps7de12f8b.jpg" alt=""></div>
<!-- Contenedor del Comentario -->
<div class="comment-box">
<div class="comment-head">
<h6 class="comment-name">#SubComment.User.UserName</h6>
<span>posted on #SubComment.Posted.ToShortDateString()</span><i>ID: #SubComment.OriginalCommentId</i>
</div>
<div class="comment-content">
#SubComment.CommentText
</div>
</div>
</li>
}
}
</ul>
</li>
</ul>
</div>
}
If you guys can figure out what the heck is wrong here, I would appreciate it. To me the code is pretty logical and should work, but it doesn't, and I've tried so many things but no luck.
Thank you in advance.
For your SubComments foreach statement:
foreach (var SubComment in Model.SubComicComments.Where(m => m.OriginalCommentId == m.ComicComment.Id))
Should be:
foreach (var SubComment in Model.SubComicComments.Where(m => m.OriginalCommentId == Comment.Id))
No? You want to check SubComment.OriginalCommentId against the id in the Comment variable declared in your enclosing Comments iteration.
As an aside, in your first foreach statement, I don't think the where clause is doing anything:
#foreach (var Comment in Model.ComicComments.Where(m => m.ComicId == m.Comic.Id))
ComicID == Comid.Id should always be true as long as your includes have loaded...

How to pass hidden Id value to controller in asp.net mvc 3

I have to pass hidden Id value to controller. So I have tried in the following way, but I am getting values.
cs.Html:
<ul id="tree" class="dd-list">
#for (int i = 0; i < Model.DomainViews.Count(); i++)
{
<li class="dd-item">
<a href="#">
#Html.CheckBoxFor(model => model.DomainViews[i].IsChecked, new { #id = #Model.DomainViews[i].DomainID })
<label for="#Model.DomainViews[i].DomainID">#Model.DomainViews[i].DomainName</label>
#Html.HiddenFor(model => Model.DomainViews[i].DomainID, new { id = "hdnDomainID" })
</a>
<ul class="dd-list">
<li class="dd-item">
<a href="#">
<input type="checkbox" id="2">
<label for="2"> Level 2 - 1</label>
</a>
<ul class="dd-list">
<li class="dd-item">
<a href="#">
<input type="checkbox" id="3">
<label for="3"> Level 3 - 1</label>
</a>
</li>
<li class="dd-item">
<a href="#">
<input type="checkbox" id="4">
<label for="4"> Level 3 - 2</label>
</a>
</li>
</ul>
</li>
</ul>
</li>
}
</ul>
How to pass #Html.HiddenFor(model => Model.DomainViews[i].DomainID, new { id = "hdnDomainID" }) value to controller:
public ActionResult RoleCreate()
{
userType type = new userType();
List<DomainView> EmpList = type.GetAllRoleModulesViews();
Role objBind = new Role();
objBind.DomainViews = EmpList;
return View(objBind);
}
In above code how i get DomainId Value ..
public List<DomainView> GetAllRoleModulesViews()
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["Admin"].ConnectionString))
{
List<DomainView> EmpList = new List<DomainView>();
SqlCommand com = new SqlCommand("MEDEIL_DomainMaster_SelectAll", conn);
com.CommandType = CommandType.StoredProcedure;
SqlDataAdapter da = new SqlDataAdapter(com);
DataTable dt = new DataTable();
conn.Open();
da.Fill(dt);
conn.Close();
foreach (DataRow dr in dt.Rows)
{
EmpList.Add(new DomainView
{
DomainID = Convert.ToInt32(dr["DomainID"]),
DomainCode = Convert.ToString(dr["DomainCode"]),
DomainName = Convert.ToString(dr["DomainName"]),
CreatedBy = Convert.ToInt32(dr["CreatedBy"] == DBNull.Value ? null : dr["CreatedBy"].ToString()),
CreatedDate = Convert.ToDateTime(dr["CreatedDate"]),
ModifiedBy = Convert.ToInt32(dr["ModifiedBy"] == DBNull.Value ? null : dr["ModifiedBy"].ToString()),
ModifiedDate = Convert.ToDateTime(dr["ModifiedDate"] == DBNull.Value ? null : dr["ModifiedDate"].ToString())
});
}
return EmpList;
}
}
Modules:
public class DomainView
{
[Key]
public int DomainID { get; set; }
public string DomainCode { get; set; }
public string DomainName { get; set; }
public int TabOrder { get; set; }
public string UserName { get; set; }
public int CreatedBy { get; set; }
public DateTime CreatedDate = DateTime.UtcNow;
public int ModifiedBy { get; set; }
public DateTime ModifiedDate = DateTime.UtcNow;
public bool IsChecked { get; set; }
public IEnumerable<DomainView> DomainViews { get; set; }
}
The easiest way I'd prefer is to use a MVC feature called Editor Templates. You would need to create a Sub-Directory EditorTemplates within the correct View Folder (or Shared Folder) and there, you'd create DomainView.cshtml. That file would contain the markup very similar to the body of your for-loop, but with DomainViews[i] removed everywhere because the Template is for a single item only:
#model DomainView // <-- you'll need your Namespace here of course
<li class="dd-item">
<a href="#">
#Html.CheckBoxFor(model => model.IsChecked, new { #id = #Model.DomainID })
<label for="#Model.DomainID">#Model.DomainName</label>
#Html.HiddenFor(model => Model.DomainID, new { id = "hdnDomainID" })
</a>
......
</li>
Within your main page, where the element <ul id="tree" class="dd-list"> is placed, your code would be:
<ul id="tree" class="dd-list">
#Html.EditorFor(model => model.DomainViews)
</ul>
The MVC Editor Template engine will generate correct names for your and when posted back, the model binder will ensure that the Array is filled correctly.

Creating an MVC form using partial views each with complex models not binding to main model

I'm working on a form that has a main model being passed to the view. The model has sub-models within it, with partial views to render that content. The problem is that when I fill out the form, only those parameters on the main form get bound back to the model when the form is submitted.
I tried changing the Html.RenderPartial to a Html.EditorFor, and while it fixed my model binding problem, it removed all of my html formatting from the partial view.
Is there a way I can either bind my partial view elements to the main form model, or keep the html structure of my partial view using EditorFor?
Below is my code (I chopped out a bunch of stuff - especially from my main view - to try to simplify what I'm looking for).
This is my model:
public class ShipJobs
{
public String Job { get; set; }
public String Quote { get; set; }
public String PartName { get; set; }
public String Rev { get; set; }
public String Customer { get; set; }
public String CustomerName { get; set; }
public String TrackingNumber { get; set; }
public Int32 ShippedQuantity { get; set; }
public Boolean Certs { get; set; }
public Double ShippingCharges { get; set; }
public DateTime ShipDate { get; set; }
public String SelectedFreightTerms { get; set; }
public IEnumerable<SelectListItem> FreightTerms { get; set; }
public String SelectedContact { get; set; }
public IEnumerable<SelectListItem> Contacts { get; set; }
public String SelectedShipVia { get; set; }
public IEnumerable<SelectListItem> ShipVia { get; set; }
public Models.GreenFolders.Address Address { get; set; }
}
public class Address
{
public AddressType Type { get; set; }
public String ShipToId { get; set; }
public String ContactName { get; set; }
public String AddressName { get; set; }
public String Line1 { get; set; }
public String Line2 { get; set; }
public String City { get; set; }
public String State { get; set; }
public String Zip { get; set; }
public String Phone { get; set; }
public SelectList ShipToAttnDropDown { get; set; }
public IEnumerable<SelectListItem> ShipToDropDown { get; set; }
}
Controller:
public ActionResult ShipJobs(String Job, Models.Shipping.ShippingModel.ShipJobs Packlist, Models.GreenFolders.Address ShipAddress, String Submit = "")
{
var Model = new Models.Shipping.ShippingModel.ShipJobs();
if (Submit == "loadjob")
{
var shippingHelper = new BLL.Shipping.ShippingMethods(_company);
Model = shippingHelper.GetShipJobModel(Job);
Model.Address = shippingHelper.GetShipAddress(Job);
}
else if (Submit == "createpacklist")
{
}
ViewBag.Company = _company.ToString();
return View(Model);
}
Main View:
#model Models.Shipping.ShippingModel.ShipJobs
#{
ViewBag.Title = "ShipJobs";
String Company = ViewBag.Company.ToString();
}
#using (Html.BeginForm("ShipJobs", "Shipping", FormMethod.Post, new { Class = "form-horizontal" }))
{
<div class="row">
<div class="col-md-6">
<!-- Basic Form Elements Block -->
<div class="block">
<!-- Basic Form Elements Title -->
<div class="block-title">
<h2>Load <strong>Job</strong></h2>
</div>
<!-- END Form Elements Title -->
<!-- Basic Form Elements Content -->
#using (Html.BeginForm("ShipJobs", "Shipping", FormMethod.Post, new { Class = "form-horizontal form-bordered" }))
{
<div class="form-group">
<label class="col-md-3 control-label" for="example-text-input">Job Number</label>
<div class="col-md-9">
#Html.TextBoxFor(model => model.Job, new { id = "example-text-input", Name = "Job", Class = "form-control" })
</div>
</div>
<div class="form-group form-actions">
<div class="col-md-9 col-md-offset-3">
<button type="submit" class="btn btn-sm btn-primary" name="submit" value="loadjob"><i class="fa fa-angle-right"></i> Load Job Info</button>
<button type="reset" class="btn btn-sm btn-warning"><i class="fa fa-repeat"></i> Reset</button>
</div>
</div>
}
</div>
</div>
<div class="col-md-6">
#if (Model.Address != null && Model.Address != null)
{
#Html.EditorFor(model => model.Address)
//Html.RenderPartial("../Shared/_Address", Model.ShipInfo);
}
</div>
#Html.HiddenFor(model => model.Quote)
#Html.HiddenFor(model => Company)
</div>
}
Partial view:
#model Models.GreenFolders.Address
<!-- Block -->
<div class="block">
<div class="block-title">
#if(Model.Type == Models.GreenFolders.AddressType.Shipping)
{
<h2 style="float: right; margin-top: -9px; margin-right: -10px;">
<div class="dropdown shiptoddl">
<button class="btn btn-default dropdown-toggle" type="button" id="shiptoddl" data-toggle="dropdown" aria-expanded="true">
#Model.ShipToDropDown.Where(x => x.Selected).FirstOrDefault().Text
<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
#foreach (SelectListItem selectlistitem in Model.ShipToDropDown)
{
<li role="presentation"><a role="menuitem" tabindex="-1" href="#" data-value="#selectlistitem.Value" data-selected="#selectlistitem.Selected">#selectlistitem.Text</a></li>
}
</ul>
</div>
#*#Html.DropDownList("shiptoddl", (SelectList)Model.ShipToDropDown, new { #class = "shiptoddl", id = "shiptoddl" })*#
</h2>
}
<h4><strong>#Model.Type.ToString()</strong> Address</h4>
</div>
#{ Html.RenderPartial("../Shared/_AddressDetails", Model); }
</div>
<!-- END Block -->

Resources