Model properties are null after submit - asp.net-mvc-4

I have this model:
public partial class Group
{
public Group()
{
this.ParameterGroup = new HashSet<ParameterGroup>();
}
public string GroupId { get; set; }
public string Responsibility { get; set; }
public virtual Text GroupDescText { get; set; }
public virtual Text GroupNameText { get; set; }
public virtual ICollection<ParameterGroup> ParameterGroup { get; set; }
}
public partial class Text
{
public Text()
{
this.ParamName = new HashSet<Parameter>();
this.ParamDesc = new HashSet<Parameter>();
this.EnumElemName = new HashSet<EnumElem>();
this.IoDeviceInfoText = new HashSet<IoDeviceInfo>();
this.IoCatText = new HashSet<IoDeviceInfo>();
this.GroupDesc = new HashSet<Group>();
this.GroupName = new HashSet<Group>();
this.Type = new HashSet<Type>();
this.ParamDispPath = new HashSet<Parameter>();
this.EnumElemText = new HashSet<EnumElem>();
this.TextValue = new HashSet<TextValue>();
}
public string TextId { get; set; }
public string XmlId { get; set; }
public virtual ICollection<Parameter> ParamName { get; set; }
public virtual ICollection<Parameter> ParamDesc { get; set; }
public virtual ICollection<EnumElem> EnumElemName { get; set; }
public virtual ICollection<IoDeviceInfo> IoDeviceInfoText { get; set; }
public virtual ICollection<IoDeviceInfo> IoCatText { get; set; }
public virtual ICollection<Group> GroupDesc { get; set; }
public virtual ICollection<Group> GroupName { get; set; }
public virtual ICollection<Type> Type { get; set; }
public virtual ICollection<Parameter> ParamDispPath { get; set; }
public virtual ICollection<EnumElem> EnumElemText { get; set; }
public virtual ICollection<TextValue> TextValue { get; set; }
}
This is my Controller:
public class GroupController : Controller
{
// GET: Group
public ActionResult Index()
{
return PartialView("Index", GroupModel.Instance.getGroups());
}
public ActionResult Edit(string id)
{
Group group = KebaContext.SessionBasedContext().GroupSet.Where(g => g.GroupId == id).FirstOrDefault();
List<Language> langs = KebaContext.SessionBasedContext().LanguageSet.ToList();
foreach(Language l in langs)
{
if(group.GroupDescText == null)
{
group.GroupDescText = new Text();
TextValue value = new TextValue();
value.TextId = Guid.NewGuid().ToString("N");
value.LangId = l.LangId;
value.Value = "";
group.GroupDescText.TextValue.Add(value);
}
if (group.GroupNameText == null)
{
group.GroupNameText = new Text();
TextValue value = new TextValue();
value.TextId = Guid.NewGuid().ToString("N");
value.LangId = l.LangId;
value.Value = "";
group.GroupNameText.TextValue.Add(value);
}
if (group.GroupDescText != null && group.GroupDescText.TextValue.Where(x => x.LangId == l.LangId).FirstOrDefault() == null) //just one lang is available
{
TextValue value = new TextValue();
value.TextId = group.GroupDescText.TextValue.First().TextId;
value.LangId = l.LangId;
value.Value = "";
group.GroupDescText.TextValue.Add(value);
}
if (group.GroupNameText != null && group.GroupNameText.TextValue.Where(x => x.LangId == l.LangId).FirstOrDefault() == null) //just one lang is available
{
TextValue value = new TextValue();
value.TextId = group.GroupNameText.TextValue.First().TextId;
value.LangId = l.LangId;
value.Value = "";
group.GroupNameText.TextValue.Add(value);
}
}
return View(group);
}
[HttpPost]
public ActionResult Edit(Group xyz)
{
return RedirectToAction("Index", "Types");
}
}
This is my View:
#using System.Web.Mvc.Html;
#model Keba.Data.EF.Group
#{
ViewBag.Title = "Group Editing";
}
<h2>Edit Group</h2>
<div id="groupEdit">
#using (Html.BeginForm("Edit", "Group", FormMethod.Post))
{
#Html.HiddenFor(model => model.GroupId);
<table class="userEditAddTable">
<tr><th>Responsibility</th><td>#Html.EditorFor(model => model.Responsibility)</td></tr>
#foreach (var name in Model.GroupNameText.TextValue)
{
#Html.HiddenFor(model => name.LangId)
#Html.HiddenFor(model => name.Value)
<tr><th>GroupNameText(#Html.DisplayFor(model => name.LangId))</th><td> #Html.TextBoxFor(model => name.Value)</td></tr>;
}
#foreach (var desc in Model.GroupDescText.TextValue)
{
#Html.HiddenFor(model => desc.LangId)
#Html.HiddenFor(model => desc.Value)
<tr><th>GroupDescText(#Html.DisplayFor(model => desc.LangId))</th><td> #Html.TextBoxFor(model => desc.Value)</td></tr>;
}
</table>
<br />
<div id="buttons">
<input name="Save" type="submit" value="Save" class="button" />
<input name="Cancel" type="submit" value="Cancel" class="button" />
</div>
}
</div>
Problem:
If I try to change the value of a Text in the group model e.g. GroupNameText.TextValue.Value send it to the controller (submit). The properties GroupNameText and GroupDescText are null.
I have also tried the solution with propertybinding ([Bind(Include = "GroupDescText,GroupNameText")] Group xyz) which also doesn't work

First, remember that only properties that are posted (i.e. have a form input element representing them) will be populated.
Second, the names of the input elements must match up to what the model binder expects on post, or it will discard the values, as it won't know what to do with them. In particular, with enumerables, this means you need to use for loops rather than foreach, so that Razor can create the right name binding:
#for (var i = 0; i < Model.GroupNameText.TextValue; i++)
{
#Html.HiddenFor(m => m.GroupNameText.TextValue[i].LangId)
#Html.HiddenFor(m => m.GroupNameText.TextValue[i].Value)
...
}
That will result in a name attribute like GroupNameText.TextValue[0].LangId, which the model binder should be able to bind appropriately, whereas your field names are currently just LangId, which is meaningless on post.

Have a look at this similar to your approach is to have a list in the view, you might need to have partials.

Related

Mapping problem when using Automapper in an Edit form with select list

I am trying to create an edit form which includes a selectlist that gets the data from the database. I am unable to display the form since I cannot map the viewmodel with the actual model using Automapper.
Contact.cs:
public int ContactId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string? EmailAddress { get; set; }
public int CompanyId { get; set; }
[ForeignKey("CompanyId")]
public Company Company { get; set; }
ContactEditViewModel.cs:
public int ContactId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string? EMailAddress { get; set; }
[Range(1, int.MaxValue, ErrorMessage = "Please select a company.")]
public int CompanyId { get; set; }
public SelectList? Company { get; set; }
Edit View
<div class="form-group">
<label asp-for="Company" class="control-label"></label>
<div class="input-group mb-3">
<select asp-for="CompanyId" class="form-select" asp-items="#Model.Company"></select>
</div>
</div>
ContactsController Edit Action:
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var contact = await _context.Contacts.FirstOrDefaultAsync(c => c.ContactId == id);
var model = new ContactEditVM
{
Company = new SelectList(_context.Companies, "CompanyId", "CompanyName"),
};
//var contact = mapper.Map<ContactEditVM>(await contactRepository.GetAsync(id));
mapper.Map(model, contact);
if (contact == null)
{
return NotFound();
}
//ViewData["CompanyId"] = new SelectList(_context.Companies, "CompanyId", "CompanyName", contact.Company);
return View(model);
}
MappingConfiguration
public class MapConfig : Profile
{
public MapConfig()
{
CreateMap<Contact, ContactListVM>().ReverseMap();
CreateMap<Contact, ContactCreateVM>().ReverseMap();
CreateMap<Contact, ContactEditVM>().ReverseMap();
}
}
The error I get is:
AutoMapperMappingException: Missing type map configuration or unsupported mapping.
Mapping types:
SelectList -> Company
Microsoft.AspNetCore.Mvc.Rendering.SelectList -> ENV.Data.Company
Destination Member:
Company
...
If I create a new instance of my viewmodel and assign values to it manually, without using Automapper, it works as intended. So what is wrong with my mapping?
Does it work if you outcomment the "Company" from your Contact.cs and outcomment the "Company" from your ContactEditViewModel.cs?
I think you need to define a mapping which tells autoMapper how to map a "SelectedList?" to a "Company".
For Example:
var autoMapperConfig = new MapperConfiguration(cfg =>
{
cfg.CreateMap<WalletData/*Source*/, BP_WalletDTO/*Destination*/>()
.ForMember(dest => dest.Id, memberOptions => memberOptions.MapFrom(src => src.Id))
.ForMember(dest => dest.Type, memberOptions => memberOptions.MapFrom(src => src.Type))
.ForMember(dest => dest.Attributes, memberOptions => memberOptions.MapFrom(src => new BP_WalletAttributesDTO
{
CryptocoinId = src.Attributes.Cryptocoin_id,
CryptocoinSymbol = src.Attributes.Cryptocoin_symbol,
Balance = src.Attributes.Balance,
IsDefault = src.Attributes.Is_default,
Name = src.Attributes.Name,
PendingTransactionsCount = src.Attributes.Pending_transactions_count,
Deleted = src.Attributes.Deleted,
IsIndex = src.Attributes.Is_index,
}));
});
Maybe this helps

How to re-Render Blazor Component witch Render by RenderFragment or re-Bind Resource for Child who Render by RenderFragment

Question :
I am looking for how to let "RenderFragment" can re-Render or re-Binding Resource .
Environment:
VS2019 Preview , .net core 6 preview (I think it is not different with 5)
What I Had Try :
My Razor Component page has a selection and a button ,
Selection will get default resource when page first render ,
Button Click Cvent should change the resource of Selection .
This is What I prefer for correct result
But Actually ,
Resource is not changing when I Using RenderFragment to create component .
Resource is not changing.
I Stop at FabArea.razor to check if button click changed oResource .
Stop at Button Clicked.
I tried to add StateHasChanged() in my code , but it didn't help when oResource has changed .
oResource Changed into B , by Selection's Resource is still same.
In some reason I have to make each "Area" ,"selection" and "button" into different component .
Here is My code .
Parent Component : DyResource.Razor
#page "/DyResource"
<h3>DyResource</h3>
<p>You Just Select : #SelectedValue </p>
<p>isDefault Resource : #(isDefaultResource?"Default Value":"Not Default Value") </p>
<p>Resource[0]: #(oResource.First().id.ToString())</p>
<FabArea Componets="#liComponets"></FabArea>
#code {
public List<iFabComponet> liComponets { get; set; }
public List<Selection> oResource { get; set; }
public string SelectedValue { get; set; }
public bool isDefaultResource { get; set; } = true;
public class Selection
{
public string id { get; set; }
public string text { get; set; }
}
public class iFabComponet
{
public Type Type { get; set; }
public string Row { get; set; }
public string Length { get; set; }
public string Seq { get; set; }
public RenderFragment Control { get; set; }
public Dictionary<string, object> Dic { get; set; }
public object TComponent { get; set; }
}
protected override void OnInitialized()
{
DefaultResource(); //Set oResource
CreateComponent();
}
//Selection Resource When First Render Pages
private void DefaultResource()
{
oResource = new List<Selection>
{
new Selection { id = "A01", text = "A01" },
new Selection { id = "A02", text = "A02" },
new Selection { id = "A03", text = "A03" },
new Selection { id = "A04", text = "A04" },
new Selection { id = "A05", text = "A05" }
};
//StateHasChanged();
}
// Selection Resource When Button Click
private void ChangedResource()
{
oResource = new List<Selection>()
{
new Selection { id = "B01", text = "B01" },
new Selection { id = "B02", text = "B02" },
new Selection { id = "B03", text = "B03" },
new Selection { id = "B04", text = "B04" },
new Selection { id = "B05", text = "B05" }
};
//StateHasChanged();
}
//Create KeyValuePair for Child Components
private void CreateComponent()
{
List<iFabComponet> FCs = new List<iFabComponet>();
var DDLDic = new Dictionary<string, object>();
DDLDic.Add("Label", "Type");
DDLDic.Add("Resource", oResource);
DDLDic.Add("TextField", "id");
DDLDic.Add("ValueField", "text");
DDLDic.Add("Enabled", true);
DDLDic.Add("Id", "ddlType");
DDLDic.Add("Width", "100%");
DDLDic.Add("ResultValueChanged", EventCallback.Factory.Create<System.String>(this, str => TypeSelected(str)));
iFabComponet FirstCom = new iFabComponet() { Type = typeof(FabDDL<string, Selection>), Row = "1", Length = "6", Seq = "1", Dic = DDLDic };
liComponets.Add(FirstCom);
var btnDic = new Dictionary<string, object>();
btnDic.Add("ButtonTitle", "Get Data");
btnDic.Add("isNeedPad", true);
btnDic.Add("PadLength", 4);
btnDic.Add("OnClick", EventCallback.Factory.Create<System.String>(this, str => BtnClick()));
iFabComponet SecCom = new iFabComponet() { Type = typeof(FabButton), Row = "2", Length = "6", Seq = "2", Dic = btnDic };
liComponets.Add(SecCom);
}
//Selection Event
private void TypeSelected(string x)
{
SelectedValue = x;
}
//Button Event
private void BtnClick()
{
if (isDefaultResource)
{
ChangedResource();
isDefaultResource = false;
}
else
{
DefaultResource();
isDefaultResource = true;
}
CreateComponent();
StateHasChanged();
}
}
FabArea.Razor (Area to show and Render Child Component)
#using System.Linq.Expressions
<div class="card">
<div class="card-body">
#foreach (var item in Contents)
{
#item
;
}
</div>
</div>
#code {
[Parameter]
public List<iFabComponet> Componets { get; set; }
public List<RenderFragment> Contents { get; set; }
protected override void OnInitialized()
{
if (Componets.Count() > 0 && Componets != null)
{
CreateFragment();
}
}
public async void CreateFragment()
{
int iComponent = 0;
List<RenderFragment> RFTs = new List<RenderFragment>();
Contents = new List<RenderFragment>();
int iContent = 1;
foreach (var area in Componets)
{
RenderFragment renderFragment = (builder) =>
{
builder.OpenComponent(iComponent, area.Type);
//Using For Checking Resource .
foreach (var item in area.Dic)
{
var q = item.Key;
var w = item.Value;
}
builder.AddMultipleAttributes(iContent, area.Dic);
builder.CloseComponent();
};
Contents.Add(renderFragment);
}
StateHasChanged();
}
}
Here is Selection Component and Button Component .
FabDDL.razor
#typeparam T
#typeparam TResource
<div class="row">
<label class="col-md-2">#Label</label>
<div class="col-md-5">
<select class="selection" id="#id" disabled="#(!Enabled)" #onchange="#(() => ResultValueChanged.InvokeAsync())">
<option></option>
#if (Resource != null)
{
#foreach (var item in Resource)
{
<option value="#(item.GetType().GetProperty(ValueField).GetValue(item))">#(item.GetType().GetProperty(TextField).GetValue(item))</option>
}
}
</select>
</div>
</div>
#code {
[Parameter] public string Label { get; set; }
//[Parameter] public T ResultValue { get; set; }
[Parameter] public List<TResource> Resource { get; set; }
[Parameter] public string DefaultText { get; set; } = "Select an Option";
[Parameter] public string id { get; set; } = "DropDownList" + Guid.NewGuid().ToString();
[Parameter] public string Width { get; set; } = "100 %";
[Parameter] public bool Enabled { get; set; }
[Parameter] public string TextField { get; set; }
[Parameter] public string ValueField { get; set; }
[Parameter] public EventCallback<T> ResultValueChanged { get; set; }
}
<style>
.selection {
width: 100%;
height: 100%;
padding-left: 15px;
}
</style>
FabButton.razor
#if (isNeedPad){<div class="#PadRowClass"></div>}
<div class="col-md-2 pt-3 middle">
<button class="btn btn-info" type="#ButtonType" #onclick="#(() => OnClick.InvokeAsync())">#ButtonTitle</button>
</div>
#code {
[Parameter] public string ButtonTitle { get; set; } = "Click ME!";
[Parameter] public string ButtonType { get; set; } = "button";
[Parameter] public EventCallback<string> OnClick { get; set; }
[Parameter] public bool isNeedPad { get; set; } = false;
[Parameter] public int PadLength { get; set; } = 1;
public string PadRowClass { get; set; }
protected override void OnInitialized()
{
PadRowClass = "col-md-" + PadLength.ToString();
base.OnInitialized();
}
}

How to deal with this decimal error for a price?

I'm working on this app that should show on "localhost/catalog" some data. I have a library for the models and for the services that the application might use. I am getting this error:
InvalidOperationException: The property 'Price' is not a navigation
property of entity type 'StoreAsset'. The 'Include(string)' method can
only be used with a '.' separated list of navigation property names.Microsoft.EntityFrameworkCore.Query.Internal.IncludeCompiler.WalkNavigations(IEntityType entityType, IReadOnlyList<string> navigationPropertyPaths, IncludeLoadTree includeLoadTree, bool shouldThrow)
Here is the code that I'm using (controller, models and view) and the service methods on bottom:
public class CatalogController : Controller
{
private IStoreAsset _assets;
public CatalogController(IStoreAsset assets)
{
_assets = assets;
}
public ActionResult Index()
{
var assetModels = _assets.GetAll();
var listingResult = assetModels
.Select(result => new AssetIndexListingModel
{
Id = result.Id,
Tipology = _assets.GetTipology(result.Id),
Size = _assets.GetSize(result.Id),
Price = decimal.Parse(_assets.GetPrice(result.Id))
});
var model = new AssetIndexModel()
{
Assets = listingResult
};
return View(model);
}
public class AssetIndexListingModel
{
public int Id { get; set; }
public string Size { get; set; }
public decimal Price { get; set; }
public string Tipology { get; set; }
public string ImageUrl { get; set; }
}
public abstract class StoreAsset
{
public int Id { get; set; }
[Required]
public Status Status { get; set; }
[Required]
public decimal Price { get; set; }
public string ImageUrl { get; set; }
}
public class Dress : StoreAsset
{
[Required]
public string Color { get; set; }
[Required]
public string Tipology { get; set; }
[Required]
public string Size { get; set; }
}
#model Models.Catalog.AssetIndexModel
<div id="assets">
<h3></h3>
<div id="assetsTable">
<table class="table table-condensed" id="catalogIndexTable">
<thead>
<tr>
<th>Size</th>
<th>Price</th>
<th>Tipology</th>
</tr>
</thead>
<tbody>
#foreach (var asset in Model.Assets)
{
<tr class="assetRow">
<td class="">
<a asp-controller="Catalog" asp-action="Detail" asp-route-id="#asset.Id">
<img src="#asset.ImageUrl" class="imageCell" />
</a>
</td>
<td class="">#asset.Price</td>
<td class="">#asset.Size</td>
<td class="">#asset.Tipology</td>
</tr>
}
</tbody>
</table>
</div>
public class StoreAssetService : IStoreAsset
{
private Context _context;
public StoreAssetService(Context context)
{
_context = context;
}
public void Add(StoreAsset newAsset)
{
_context.Add(newAsset);
_context.SaveChanges();
}
public IEnumerable<StoreAsset> GetAll()
{
return _context.StoreAssets
.Include(asset => asset.Status)
.Include(asset => asset.Price);
}
public StoreAsset GetById(int id)
{
// Return a query (same as returning GetAll().FirstOrDefault(...))
return _context.StoreAssets
.Include(assets => assets.Status)
.Include(assets => assets.Price)
// So it can return null with no problem
.FirstOrDefault(asset => asset.Id == id);
}
public StoreBranch GetCurrentLocation(int id)
{
throw new NotImplementedException();
}
// To implement and test
public string GetPrice(int id)
{
return _context.Dresses.FirstOrDefault(p => p.Id == id).Price.ToString();
}
public string GetSize(int id)
{
return _context.Dresses.FirstOrDefault(s => s.Id == id).Size;
}
public string GetStatus(int id)
{
throw new NotImplementedException();
}
public string GetTipology(int id)
{
var dress = _context.StoreAssets.OfType<Dress>()
.Where(b => b.Id == id);
// For now return other if it's not a party dress
return dress.Any() ? "Party" : "Other";
}
}
Should I use some ForeignKey attribute or change Price to a string?
Any help would be great thanks
As pointed out in the error message, the Include is for the Navigation property only.
You need to change below:
return _context.StoreAssets
.Include(asset => asset.Status)
.Include(asset => asset.Price);
To:
return _context.StoreAssets
.Include(asset => asset.Status).ToList();
Reference: https://learn.microsoft.com/en-us/ef/core/modeling/relationships#definition-of-terms
https://learn.microsoft.com/en-us/ef/core/querying/related-data
I am having yet another problem. When I go to "localhost/catalog" the page should display all columns/entries that I have in the database but it only displays one column. Is there something wrong in the foreach cicle?

search function in ASP.NET MVC not working properly

i have a student table in my database that i created and i have a view that displays a list of all the students grouped by class... on top of the view i made a textbox and a search button to be able to access the student information faster. The problem is that i when i enter the first name and the last name in the textbox, nothing comes up. When i enter only the first name or only the last name, then it finds it. I'm new to programming and i can't figure out how to make it work. I would really appreciate if someone can help me with this. This is part of my code:
[HttpGet]
public ActionResult ViewStudents()
{
ViewBag.classes = db.Courses.ToList();
var studentCourses = db.StudentCourses.OrderBy(s=>s.Person.FirstName).ToList();
return View(studentCourses);
}
[HttpPost]
public ActionResult ViewStudents(string SearchString)
{
var student=new List<int>();
List<StudentCourse>sc=new List<StudentCourse>();
ViewBag.classes = db.Courses.ToList();
var studentCourse=db.StudentCourses.ToList();
var studentCourses = db.StudentCourses.OrderBy(s => s.Person.FirstName).ToList();
var substring = SearchString.IndexOf(" ").ToString();
if (!string.IsNullOrEmpty(SearchString))
{
student = (from p in db.People
where (p.FirstName.Contains(SearchString)) && (p.LastName.Contains(substring))||((p.FirstName.Contains(SearchString)) || (p.LastName.Contains(SearchString)))
select p.PersonId).ToList();
}
foreach (var s in studentCourse)
{
foreach (var i in student)
{
if (s.StudentId == i)
{
sc.Add(s);
}
}
}
return View(sc);
}
This is my view:
#model List<SchoolFinalProject.Models.StudentCourse>
#using (Html.BeginForm())
{
<div style="font-size:16px;"> <input type="text" id="search" placeholder="search" Name="SearchString" /><span class="glyphicon glyphicon-search"></span>
<input type="submit" value="search"></div>
}
#{
List<int> c = new List<int>();
foreach (var courses in ViewBag.classes)
{
foreach(var s in Model)
{
if(courses.CourseId==s.CourseId)
{
c.Add(courses.CourseId);
}
}
}
}
#foreach (var course in ViewBag.classes)
{
if(c.Contains(course.CourseId))
{
<h2>#course.Name<span>-</span>#course.Gender</h2>
<table class="table table-hover table-bordered table-striped">
<tr><th>First Name</th><th>Last Name</th><th>Email</th><th>Phone Number</th><th>Address</th><th>Date Of Birth</th></tr>
#foreach (var s in Model)
{
if(course.CourseId==s.CourseId)
{
<tr>
<td>#s.Person1.FirstName</td>
<td>#s.Person1.LastName</td>
<td>#s.Person1.Email</td>
<td>#s.Person1.PhoneNumber</td>
<td>#s.Person1.Address</td>
<td>#s.Person1.DateOfBirth</td>
<td>
<span class="glyphicon glyphicon-edit"></span>
#Html.ActionLink("Edit", "Edit","Person", new { id = s.Person1.PersonId }, null) |
<span class="glyphicon glyphicon-trash"></span>
#Html.ActionLink("Details", "Details","Person", new { id = s.Person1.PersonId }, null)
</td>
</tr>
}
}
</table>
}
}
Go to top of page
this is my person Model:
public partial class Person
{
public Person()
{
this.Bonus = new HashSet<Bonu>();
this.ConversationHistories = new HashSet<ConversationHistory>();
this.ConversationHistories1 = new HashSet<ConversationHistory>();
this.EmployeePaymentDetails = new HashSet<EmployeePaymentDetail>();
this.StudentCourses = new HashSet<StudentCourse>();
this.StudentCourses1 = new HashSet<StudentCourse>();
this.TeacherCourses = new HashSet<TeacherCourse>();
this.Reminders = new HashSet<Reminder>();
}
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public string Address { get; set; }
public Nullable<System.DateTime> DateOfBirth { get; set; }
public PersonType PersonTypeId { get; set; }
public Nullable<System.DateTime> LastModified { get; set; }
public Nullable<int> Gender { get; set; }
public Nullable<int> Status { get; set; }
public string FullName
{
get { return FirstName + ", " + LastName; }
}
public virtual ICollection<Bonu> Bonus { get; set; }
public virtual ICollection<ConversationHistory> ConversationHistories { get; set; }
public virtual ICollection<ConversationHistory> ConversationHistories1 { get; set; }
public virtual ICollection<EmployeePaymentDetail> EmployeePaymentDetails { get; set; }
public virtual ICollection<StudentCourse> StudentCourses { get; set; }
public virtual ICollection<StudentCourse> StudentCourses1 { get; set; }
public virtual ICollection<TeacherCourse> TeacherCourses { get; set; }
public virtual ICollection<Reminder> Reminders { get; set; }
}
}
You might want to try concatenating the first and last name properties in your person model like this:
[Display(Name = "Full Name")]
public string FullName
{
get
{
return LastName + ", " + FirstMidName;
}
}
There is a very good tutorial on what you are trying to do here: https://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-a-more-complex-data-model-for-an-asp-net-mvc-application
Also see this page of same tutorial: https://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/sorting-filtering-and-paging-with-the-entity-framework-in-an-asp-net-mvc-application
As an aside, you might want to check out using the Datatables plugin, which gives you search functionality without have to query your database with each search: https://datatables.net

Range Validation is not working

I have used range validation but this is not working. I am adding model,controller and view code.Please help(i have added only related fields only in this code).
Model is :
public class TicketDetailModel : TicketModelBase
{
public WorkOnTicketCreateModel WorkOnTicketCreateModel { get; set; }
}
public class TicketModelBase
{
[Required]
[Range(1, int.MaxValue, ErrorMessage = "Please enter a value bigger than {0}")]
public int EstimatedTime { get; set; }
public virtual List<WorkOnTicket> WorkOnTickets { get; set; }
}
public class WorkOnTicketCreateModel : WorkOnTicketModelBase
{
[Required]
[Display(Name = "AssignedToUser")]
public int AssignedToUserId { get; set; }
public IEnumerable<SelectListItem> AssignedUser { get; set; }
[Required]
[Display(Name = "Ticket Status")]
public int TicketStatusId { get; set; }
public TicketStatus TicketStatusVal { get; set; }
public IEnumerable<SelectListItem> TicketStatus { get; set; }
}
public class WorkOnTicketModelBase
{
public int Id { get; set; }
[Required]
public int EstimateHours { get; set; }
[Required]
[Range(1, int.MaxValue, ErrorMessage = "Please enter a value bigger than {0}")]
public int WorkedHours { get; set; }
}
Contoller:
[HttpPost]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Details(TicketDetailModel model, IEnumerable<HttpPostedFileBase> file)
{
using (ITransaction transaction = this.nhSession.BeginTransaction())
{
var ticketObj = this.nhSession.QueryOver<Ticket>().Where(t => t.Id == model.Id).SingleOrDefault();
var workOnTicket = new WorkOnTicket();
workOnTicket.Ticket = ticketObj;
workOnTicket.WorkedHours = model.WorkOnTicketCreateModel.WorkedHours;
workOnTicket.EstimateHours = model.WorkOnTicketCreateModel.EstimateHours;
ticketObj.WorkOnTickets.Add(workOnTicket);
this.nhSession.Save(ticketObj);
transaction.Commit();
}
return RedirectToAction("Details", new { id = model.Id, milestoneId = model.Milestone.Id, projectId = model.Project.Id });
}
View:-
#model AnkTech.TicketManagement.Web.Models.Ticket.TicketDetailModel
#using (Html.BeginForm("Details", "Ticket", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true)
#Html.TextBoxFor(model => model.WorkOnTicketCreateModel.EstimateHours, new { #id = "work_remaining", #class = "s-mini", size = "2" })
Worked hours: #Html.TextBoxFor(model => model.WorkOnTicketCreateModel.WorkedHours, new { #id = "worked_hours", #class = "s-mini", size = "2" })
<input type="submit" value="Submit" tabindex="2" name="commit" id="submit-comment"
class="gray-btn">
}
I have deleted all rmaining fields. i have added only fields to which related i am asking, please help.
You need to use ModelState.IsValid to check that the model is actually valid. Currently you assign validation attributes but never check them:
[HttpPost]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Details(TicketDetailModel model, IEnumerable file) {
if (!ModelState.IsValid)
{
// Handle error
}
else
{
using (ITransaction transaction = this.nhSession.BeginTransaction()) {
var ticketObj = this.nhSession.QueryOver<Ticket>().Where(t => t.Id == model.Id).SingleOrDefault();
var workOnTicket = new WorkOnTicket();
workOnTicket.Ticket = ticketObj;
workOnTicket.WorkedHours = model.WorkOnTicketCreateModel.WorkedHours;
workOnTicket.EstimateHours = model.WorkOnTicketCreateModel.EstimateHours;
ticketObj.WorkOnTickets.Add(workOnTicket);
this.nhSession.Save(ticketObj);
transaction.Commit();
}
}
return RedirectToAction("Details", new { id = model.Id, milestoneId = model.Milestone.Id, projectId = model.Project.Id });
}