Insert Data to tblEducation using asp.net mvc 2.0 - asp.net-mvc-2

I have 2 tables in database:tbleducation,tblemployee.Anyway for table tblemployee, I have fields: employeeID,employeeName....I want to insert data into tbleducation that have fields such as:EmployeeID,Duration,.....And for the EmployeeID of table tbleducation I want to do the dropdownlist that list all EmployeeName in tblEmployee into dropdownlist.And I have code as below:
View
<div id="Education">
<%Html.EnableClientValidation(); %>
<% using (Html.BeginForm("Education","EmployeeProfile")){%>
<% Html.ValidationSummary(true, "Unsuccessfull"); %>
<table>
<tr>
<td>Employee Name</td>
<td><%= Html.DropDownListFor(x => x.EmployeeName, Model.Employee, "select EmployeeName")%</td>
<td>Duration</td>
<td><%: Html.TextBoxFor(m=> m.Duration, new { id="duration",name="duration"})%>
<%: Html.ValidationMessageFor(m => m.Duration) %></td>
<tr>
<td><input type="submit" name="add" id="add" value="Add" /></td>
</tr>
</table>
<%}%>
</div>
Model
public class UserModels
{
public string EmployeeName { get; set; }
public int EmployeeCode { get; set; }
public IEnumerable<SelectListItem> Employee { set; get; }
}
Controller
public ActionResult Education() {
var query = (from e in context.tblEmployee_Employee
select new
{
empID = e.Code,
EmpName = e.NameEng
}
).ToList();
var model = new UserModels();
var _Emp = query;
foreach (var item in _Emp)
{
model.EmployeeCode = item.empID;
model.EmployeeName = item.EmpName;
model.Employee = new SelectList(_Emp, "EmpName", "EmpName");
}
return View(model);
}
[HttpPost]
public ActionResult Education(UserModels model, FormCollection edu) {
tblEmployee_Education education = new tblEmployee_Education();
education.Duration = edu["Duration"].ToString();
education.Certificate = edu["Certificate"].ToString();
education.Country = edu["Country"].ToString();
education.SchoolName = edu["SchoolName"].ToString();
education.Major = edu["Major"].ToString();
education.SubDescript = edu["SubDescript"].ToString();
string EName = edu["EmployeeName"].ToString();
return Content(
string.Format(
"Selected role for {0} is {1}", model.EmployeeName, model.EmployeeCode
)
);
context.AddTotblEmployee_Education(education);
context.SaveChanges();
return View("Personal");
}
I got the warning message "unreachble code detected".I really do not know how to solve it.Please kindly help me,
Thanks in advanced,

In your POST action, here:
return Content(
string.Format(
"Selected role for {0} is {1}", model.EmployeeName, model.EmployeeCode
)
);
you have already returned a result and the action execution ends.
So get rid of the lines that follow it, they will never be executed:
context.AddTotblEmployee_Education(education);
context.SaveChanges();
return View("Personal");
And if you want them to be executed, then remove the return Content(...) line.

Related

controller post action not able catch list of objects

It may duplicate question, i have searched all over but couldn't satisfied, so i am posting here question.
I have object as (generated from entity framework),
public partial class Usp_Sel_NotEnteredStringResources_Result
{
public string name { get; set; }
public Nullable<int> Value { get; set; }
public int StringResourceId { get; set; }
public Nullable<int> LanguageId { get; set; }
}
and view i have created as,
#{
ViewBag.Title = "Resource Entry Languagewise";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>ResourceEntry</h2>
#using (Html.BeginForm("ResourceEntry", "LangResource", FormMethod.Post))
{
<fieldset>
<table>
#for (int i = 0; i < Model.ToList().Count; i++)
{
<tr>
<td>#Html.DisplayFor(m => Model.ElementAt(i).name)</td>
<td>#Html.TextBoxFor(m => Model.ElementAt(i).Value)</td>
#Html.HiddenFor(m => Model.ElementAt(i).LanguageId)
#Html.HiddenFor(m => Model.ElementAt(i).name)
#Html.HiddenFor(m => Model.ElementAt(i).StringResourceId)
</tr>
}
</table>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
And Controller as,
[HttpPost]
public ActionResult ResourceEntry(List<Usp_Sel_NotEnteredStringResources_Result> list)
{
// here getting the null value for list
// ??????
return View(list);
}
After submitting the form controller gets null value for list, what is wrong with code??
You cannot use .ElementAt(). If you inspect the html your generating you will see that the name attribute has no relationship to your model.
You model needs to implemet IList<Usp_Sel_NotEnteredStringResources_Result> and use a for loop
#for (int i = 0; i < Model.Count; i++)
{
<tr>
<td>#Html.DisplayFor(m => m[i].name)</td>
<td>
#Html.TextBoxFor(m => m.[i]Value)
// note you hidden inputs should be inside a td element
#Html.HiddenFor(m => m[i].LanguageId)
....
</td>
</tr>
}
Alternative if the model is IEnumerable<Usp_Sel_NotEnteredStringResources_Result>, you can use an EditorTemplate (refer [Post an HTML Table to ADO.NET DataTable for more details on how the name attributes must match your model property names, and the use of an EditorTemplate)

How to edit nested collections in MVC5?

I have a EF-model which contains a "key" and a "value". The value-table contains a FK to the key. In the EF-model it looks like this:
public partial class dict_key
{
public dict_key()
{
this.dict_value = new HashSet<dict_value>();
}
public int id { get; set; }
public string name { get; set; }
...
public virtual ICollection<dict_value> dict_value { get; set; } //dict_value contains a string "value"
}
My controller is passing the information for editing like this:
// GET: Keys/Texts/5
[Authorize]
public async Task<ActionResult> Texts(int? id)
{
var key = await db.dict_key
.Include(x => x.dict_value)
.Where(x => x.id.Equals(id.Value))
.FirstOrDefaultAsync();
return View(key);
// Debugging 'key' shows that dict_value has 3 correct values.
}
This gets passed to my View which shows the dict_value's correct:
#model Dict.Models.dict_key
#using (Html.BeginForm())
{
<div>Key: #Model.name </div>
<table class="table">
<tr>
<th>Language</th>
<th>Text</th>
</tr>
#for (var i = 0; i < Model.dict_value.Count(); i++)
{
<tr>
<td> #Model.dict_value.ElementAt(i).dict_lang.name_en </td>
<td> #Html.EditorFor(x => x.dict_value.ElementAt(i).value) </td>
</tr>
}
<div class="form-group">
<input type="submit" value="Save" />
</div>
</table>
}
When submitting my changes back to the controller...
[HttpPost]
public async Task<ActionResult> Texts(dict_key dict_key)
{
if (ModelState.IsValid)
{
//Also tried: db.Entry(dict_key).State = EntityState.Modified;
db.Entry(dict_key.dict_value).State = EntityState.Modified;
await db.SaveChangesAsync();
return RedirectToAction("Texts");
}
return View(dict_key);
}
..then my "dict_key" is totally different from the object I passed to my edit-view. The passed object contained the collection of dict_value's and the "returned" and edited object returns with the proper key object, but with an empty dict_value collection.
I try to avoid using a userdefined model or the viewbag to do all of that stuff manually. What is the best practise solution for this?
Collection.ElementAt doesn't generate a proper field name in Razor. You need a List. Here you should use a view model instead of your entity directly and simply make your dict_value collection a List<dict_value> there.
Alternatively, you can create an editor template for dict_value and then in your view just do:
#Html.EditorFor(m => m.dict_value)
Where dict_value there is your entire collection. Razor will render an instance of the editor template for each member of the collection and properly index everything.

LINQ to Entities error when trying to bind a dropdownlist

I am trying to create a viewmodel and add a SelectListItem to allow me to bind a dropdown list.
I have a very basic viewmodel that looks like this
public class CreatePurchaseViewModel
{
public Product Product { get; set; }
public IEnumerable<SelectListItem> Products { get; set; }
public int SelectedProductId { get; set; }
public DateTime OrderDate { get; set; }
public bool OrderSent { get; set; }
}
My controller looks like this
[HttpGet]
public ActionResult Create()
{
var model = new CreatePurchaseViewModel
{
Products = context.Products.Select(x =>
new SelectListItem()
{
Text = x.ProductName,
Value = x.ProductID
})
};
return View(model);
}
However it complains that Value = x.Product cant convert type int to string. So if I add a .ToString it compiles ok but when I try load the view I get an error
LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression.
My View
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>CreatePurchaseViewModel</legend>
<div class="editor-label">
#Html.LabelFor(model => model.SelectedProductId)
</div>
<div class="editor-field">
#Html.DropDownListFor(x => x.SelectedProductId,Model.Products)
#Html.ValidationMessageFor(model => model.SelectedProductId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.OrderDate)
</div>
<div class="editor-field">
#Html.TextBoxFor(model=>model.OrderDate)
#Html.ValidationMessageFor(model => model.OrderDate)
</div>
<div>
Sent
#Html.RadioButtonFor(model => model.OrderSent, "Sent", new { #checked = true })
Not Sent
#Html.RadioButtonFor(model=>model.OrderSent,"Not Sent")
Im pretty new to both entity framework and mvc so any help would be great.
Thank you
You haven't specified how does your Product model look like but we can assume that the ProductID property is integer so you might need to convert it to a string:
[HttpGet]
public ActionResult Create()
{
var model = new CreatePurchaseViewModel
{
Products = context.Products.Select(x =>
new SelectListItem
{
Text = x.ProductName,
Value = x.ProductID.ToString()
}
)
};
return View(model);
}

Why when I pass a Lambda expressin Func thats give me an error

When I pass call a Generic Method that return A Func and pass in parameter of the Where, that's dosen't work. (System.InvalidOperationException: Internal .NET Framework Data Provider error 1025.)
The error is when I want to get the Role information.
For the Role, I need to perform a Where Clause Expression EX: (p => p.LangID == 1)
This code dosen't Work
In the repository
public Func<T, bool> GetLmbLang<T>() where T:class,IBaseGenericTxt
{
int lang = -1;
lang = Convert.ToInt32(HttpContext.Current.Session["Language"]);
return (p => p.LangID == lang);
}
In the controller
var ViewModel = _db.Contacts.Where(a=> a.IsActive == true).Select(a => new ContactListViewModel {
ContactID = a.ContactID,
ContactName = a.ContactName,
Role = a.ContactType.ContactTypeTexts.Where(repGeneric.GetLmbLang<ContactTypeText>()).Select(af => af.Txt).FirstOrDefault(),
CompanyType = a.Supplier.SupplierName,
Addr = a.Address ,
Email = a.ContactEmail,
Phone = a.ContactPhone
}).ToList();
for (int i = 0; i < ViewModel.Count(); i++)
{
Response.Write(ViewModel.ElementAt(i).ContactID + "<br />");
}
This code WORK
int lang = -1;
lang = Convert.ToInt32(Session["Language"]);
var ViewModel = _db.Contacts.Where(a=> a.IsActive == true).Select(a => new ContactListViewModel {
ContactID = a.ContactID,
ContactName = a.ContactName,
Role = a.ContactType.ContactTypeTexts.Where(p => p.LangID == lang).Select(af => af.Txt).FirstOrDefault(),
CompanyType = a.Supplier.SupplierName,
Addr = a.Address ,
Email = a.ContactEmail,
Phone = a.ContactPhone
}).ToList();
for (int i = 0; i < ViewModel.Count(); i++)
{
Response.Write(ViewModel.ElementAt(i).ContactID + "<br />");
}
My ContactListViewModel
public class ContactListViewModel
{
public int ContactID { get; set; }
public string ContactName { get; set; }
public string Role { get; set; }
public string Company { get; set; }
public string CompanyType { get; set; }
public Address Addr { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
My List View
..... Inherits="System.Web.Mvc.ViewPage<List<mvcinfosite.ViewModels.ContactListViewModel>>" %>
<table class="genTable">
<% for (int i = 0;i < Model.Count; i++) { %>
<tr>
<td>
<%: Html.ActionLink(item.ContactName, "Edit", new { id=item.ContactID }) %>
</td>
<td>
<%: item.Role %>
</td>
<td>
<%: item.Company %>
</td>
<td>
<%: item.CompanyType %>
</td>
<td>
<%: GlobalHelper.GetAddress(item.Addr) %>
</td>
<td>
<%: item.Email %>
</td>
<td>
<%: item.Phone %>
</td>
</tr>
<% } %>
</table>
As naasking points out, you need to use an Expression of a Func instead of a straight Func:
public Expression<Func<T, bool>> GetLmbLang<T>() where T:class,IBaseGenericTxt
{
int lang = -1;
lang = Convert.ToInt32(HttpContext.Current.Session["Language"]);
return (p => p.LangID == lang);
}
Edit
Ah, yes, well the problem is that your function doesn't actually know what class it's working with at compile time: it only knows that it's a class, and it implements IBaseGenericTxt. So when you say p.LangId, that part of the expression is calling IBaseGenericTxt.LangId, and not ContactTypeText.LangId.
You'll need to build your own expression tree in order to get this to work right. Something like this:
var paramExpr = Expression.Parameter(typeof(T), "p");
return Expression.Lambda<Func<T, bool>>(
Expression.Equal(
Expression.Property(paramExpr, "LangId"),
Expression.Constant(lang)),
paramExpr);
Edit 2
Two things:
Because LINQ to Entities will try to take anything in a query expression and convert it to a SQL statement, you have to be careful not to go calling methods in the middle of your query. You'll want to call the GetLmbLang method first and store its value in a variable to use in the query.
As you point out in your comment, because the ContactTypeTexts property does not implement IQueryable, this gets particularly tricky. You have three options as far as I can tell:
Create your entire select statement as an expression tree. This is very annoying and error-prone.
Use Joe Albari's LinqKit to "Compile" and "Expand" your query. LinqKit will traverse the expression tree and build a new tree wherein your query Expression is converted to its equivalent Func.
Go back to your data context rather than using the ContactTypeTexts property.
Personally, I would probably go with the last option, like this:
var lambdaLang = repGeneric.GetLmbLang<ContactTypeText>();
var ViewModel = _db.Contacts
.Where(a=> a.IsActive == true)
.Select(a => new ContactListViewModel {
ContactID = a.ContactID,
ContactName = a.ContactName,
Role = _db.ContactTypeTexts
.Where(ct => ct.ContactType.Contacts.Any(
c => c.ContactId == a.ContactId)
.Where(lambdaLang)
.Select(af => af.Txt).FirstOrDefault(),
CompanyType = a.Supplier.SupplierName,
Addr = a.Address ,
Email = a.ContactEmail,
Phone = a.ContactPhone
}).ToList();
The latter code works because the C# compiler converts it into an expression tree, ie. System.Linq.Expression, whereas your original code was compiled as a Func. Linq to SQL as currently designed cannot process the Func, only expression trees.

ModelBinder NHibernate Complex Object with Collections

Below, on initial load (Edit), everything displays fine. However, when I POST (Action below), it looks like it goes and tries to grab the ProductAttribute models separately, with the Product's id, which promptly fails. How to keep my Binder implementation from trying to re-bind Collections as separate entities?
Thanks!
Model
public class Product {
virtual public long Id { get; set; }
virtual public string Name { get; set; }
private IList<ProductAttribute> _productAttributes;
public virtual IList<ProductAttribute> ProductAttributes {
get{
if(_productAttributes == null){
_productAttributes = new List<ProductAttribute>();
}
return _productAttributes;
}
set{
_productAttributes = value;
}
}
}
View
<%using (Html.BeginForm(new {id = Model.Id > 0 ? (long?)Model.Id : null})) {%>
<table class="form">
<% for(var i=0; i < Model.ProductAttributes.Count; i++){
var pa = Model.ProductAttributes[i]; %>
<tr>
<th><%: Model.ProductAttributes[i].Name %></th>
<td>
<%: Html.Hidden("ProductAttributes.Index", i) %>
<% if(pa.CanSpecifyValueDirectly()){ %>
<%: Html.TextBoxFor(model => model.ProductAttributes[i].Value) %>
<% } else { %>
<%: Html.DropDownListFor(model => model.ProductAttributes[i].Value, new SelectList(pa.MarketAttribute.AttributeLevels, "id", "Name", pa.AttributeLevel)) %>
<% } %>
</td>
</tr>
<input type="submit" value="Save" />
</table>
<%}%>
Controller
public ActionResult Edit(long id, Product product) {
ViewData.Model = product;
if (ModelState.IsValid) {
var results = product.Update();
ViewData["results"] = results;
if (!results.Error) {
return RedirectToAction("Show", new { id = id });
}
}
return View();
}
Binder
public class StackModelBinder : DefaultModelBinder {
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) {
var modelInterface = modelType.GetInterface("IModel");
if (modelInterface == null) {
return base.CreateModel(controllerContext, bindingContext, modelType);
}
var value = bindingContext.ValueProvider.GetValue("id").RawValue.ToString();
if (string.IsNullOrEmpty(value)) {
return base.CreateModel(controllerContext, bindingContext, modelType);
}
var id = Convert.ChangeType(value, typeof (long));
var assembly = Assembly.GetAssembly(modelType);
var dao = assembly.GetType(string.Concat(assembly.GetName().Name, ".core.GlobalDao`1[", modelType.FullName, "]"));
if (dao == null) {
return base.CreateModel(controllerContext, bindingContext, modelType);
}
var method = dao.GetMethod("Get");
return method.Invoke(null, new[] {id});
}
}
Typically, it is a bad idea to push entities through the model binder--they tend to be a bit too complex for it to handle, never mind the exciting stuff that goes on in modern ORMs, such as dynamic proxies, that can give the ModelBinder or the ORM fits.
Your best bet here is to change the rules and build a dedicated class for taking the edits and transferring that to the controller. This class can be ModelBinder-friendly and you get the added benefit of separating the UI from the domain entities.