no accessible extension method - c#

The view is not able to get my GridData, not sure why.
The code pass the GridData in the view, but the view page is not able to access GridData object.
UserMaster Models:
namespace Project.Models
{
public class UserMaster
{
[Key]
public int UserId { get; set; }
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Required]
}
public class UserMasterList
{
public List<UserMaster> GridData { get; set; }
}
}
Control:
UserMasterList userMasterList = new UserMasterList();
List<UserMaster> gl = new List<UserMaster>();
var userMasterListResult = _context.UserMaster.FromSql("EXECUTE [dbo].[UserMaster_Get] {0}", 0).ToList();
foreach (var data in userMasterListResult)
{
gl.Add(data);
}
userMasterList.GridData = gl;
return View(userMasterList);
View:
#model Project.Models.UserMaster
#foreach (var data in #Model.GridData) {
<tr>
<td>
#Html.DisplayFor(modelItem => data.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => data.LastName)
</td>
</tr>
}
Error:
The code pass the GridData in the view, but the view page is not able to access GridData object.

in view, you should have
#model Project.Models.UserMasterList

In your controller you are passing an object with type of UserMasterList, but in your view, model is type of UserMaster so that you should update used model in view as like as below:
#model Project.Models.UserMasterList

Related

MVC- Count Number of Records

Edit My view is using the Employer model. Employer and JobPosting have a 1:M relationship. I will share more of the view for context.
Context: In my application, I want to show the Employer the number of applicants who applied for their JobPosting. The code that I currently have written is not returning any value. It's not throwing any errors- but it's not working either. I'm pretty sure the issue is in my controller, but I'll provide the Model and View as well.
Controller:
public ActionResult AppCount()
{
foreach (var app in db.JobPostings.ToList())
{
int id = app.JobPostingID;
int count= db.Applications.Where(a => a.JobPostingID == id).Count();
app.AppCount = count;
ViewBag.AppCount = count;
}
return View();
}
View:
#model InTurn_Model.Employer
.
.
.
<h2>My Job Postings</h2>
<p>
#Html.ActionLink("Create New", "Create", "JobPostings", null, null)
</p>
<div id="employeeContainer"></div>
<table class="table table-striped">
<tr>
<th>Position</th>
<th>Job Type</th>
<th>Number of Applicatiosn</th>
<th></th>
</tr>
#foreach (var item in Model.JobPostings)
{
if (item.EmployerID == Model.EmployerID)
{
<tr>
<td>
#Html.DisplayFor(model => item.Position)
</td>
<td>
#Html.DisplayFor(model => item.JobType)
</td>
<td>#ViewBag.AppCount</td>
<td>#Html.ActionLink("Details", "Details", "JobPostings", new { id = item.JobPostingID }, null) </td>
</tr>
}
}
</table>
Model:
[MetadataType(typeof(JobPostingMetaData))]
public partial class JobPosting
{
public int AppCount { get; set; }
private sealed class JobPostingMetaData
{
[Display(Name = "Job Posting ID")]
public int JobPostingID { get; set; }
[Display(Name = "Employer ID")]
public int EmployerID { get; set; }
[Display(Name = "Description")]
public string Desc { get; set; }
[Display(Name = "Job Type")]
public JobType JobType { get; set; }
[Display(Name = "Employment Type")]
public TimeType TimeType { get; set; }
[DataType(DataType.Currency)]
public decimal Wage { get; set; }
}
}
There are two problems that I see.
First, you are not passing Model from controller to view. However, you are iterating through Model.JobPostings. It is empty.
Second, you assign ViewBag.AppCount in the loop. So, all values, except for the last one are lost. But if you fix the first problem (use Model instead of ViewBag) - the second might go away by itself.
You need to specify the model in the view with #model:
#model YourNameSpace.JobPosting
Then return that model to the view:
public ActionResult AppCount()
{
foreach (var app in db.JobPostings.ToList())
{
int id = app.JobPostingID;
int count= db.Applications.Where(a => a.JobPostingID == id).Count();
app.AppCount = count;
ViewBag.AppCount = count;
}
return View(app);
}
This will make the values in the model available to the view. There is no need to use ViewBag, as AppCount is part of the model.
I was overthinking this. I just needed to set this up from the JobPosting model, and then the rest worked, I didn't need to iterate through the Controller at all.
public int AppCount => Applications.Count;

Save checkbox list value Sql database in MVC5

I want to store fields and checkboxes in a database table in a form: The connection table contains the following fields:
connection table:
public partial class Connection
{
[Key]
public int ID { get; set; }
public string CommunicationName { get; set; }
public bool IsSelected { get; set; }
}
Register table:
public class RegisterForm
{
#region Ctor
public RegisterForm()
{
}
#endregion Ctor
#region Properties
[Key]
[Required]
public int ID { get; set; }
[Required(ErrorMessage = ("Required"))]
[StringLength(50, ErrorMessage = "This field must be a maximum of 50 characters")]
[TypeConverter("NVarchar(121)")]
[DisplayName("FullName")]
public string FullName { get; set; }
public string Email { get; set; }
public List<Connection> Communications { get; set; }
}
The values of the checkbox fields in the list are displayed using the following method:
questionForm.Communications = db.Connections.ToList<Connection>();
Now how to save the information in the post and save it to the register table. ????????? What changes should be Create to the update, delete operation in the register?
controller for register:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,FullName,PhoneNumber,Email,Communication,")]RegisterForm questionForm)
{
if (ModelState.IsValid)
{
db.Registers.Add(questionForm);
var data = db.SaveChanges();
return View("FormSuccessfullySubmitted");
}
return View(questionForm);
}
You should read about MVC model binding. Normally it could bound it without any problem. But lists are slightly different. You are to provide index of item in list. That is why it is better to use for, instead of foreach.
Check this view and grab it POSTed values to examine. Pay attention, that all list items are displayed using its index in list.
<table class="table">
#using (Html.BeginForm("Bind", "Bind", FormMethod.Post))
{
for (int i = 0; i < Model.Count(); i++)
{
<tr>
<td>
#Html.DisplayFor(modelItem => Model[i].CommunicationName)
</td>
<td>
#Html.CheckBoxFor(modelItem => Model[i].IsSelected)
</td>
</tr>
}
<button type="submit">Submit</button>
}
</table>

.net mvc declare a property to hold a collection of generic objects?

I have an MVC proyect using EF (database first) and I have already created CRUD for some entities.
Now I am trying to create a dashboard page that contains widgets or similar, each listing the last 10 entities from different db tables (last 10 products created, last 10 customers, etc)
To create the widget I have followed this tutorial https://www.codeproject.com/Articles/598383/Widgets-in-MVC
So I have 2 interfaces and 2 classes that implements those interfaces:
public interface IWidget
{
int SortOrder { get; set; }
string Entity { get; set; }
string CssClassName { get; set; }
string HeaderText { get; set; }
string FooterText { get; set; }
ISubWidget SubWidget { get; set; }
}
public interface ISubWidget
{
ICollection<Products> EntitiesList { get; set; }
}
public class Widget : IWidget
{
public int SortOrder { get; set; }
public string Entity { get; set; }
public string HeaderText { get; set; }
public string FooterText { get; set; }
public ISubWidget SubWidget { get; set; }
}
public class SubWidget : ISubWidget
{
public ICollection<Products> EntitiesList { get; set; }
}
then I have 3 partial views: one for the widget itself, one for the subwidget, and one that will act as a container of all created widgets.
#model Proyect.Comun.Widget.IWidget
<div class="widget">
<div class="#Model.CssClassName">
<div class="widgetHeader">
#Model.HeaderText
</div>
<div class="widgetBody">
#Html.Partial(string.Concat(new[] { "Widget", "/", "_SubWidget" }), #Model.SubWidget)
</div>
<div class="widgetFooter">
#Model.FooterText
</div>
</div>
</div>
#model Proyect.Comun.Widget.ISubWidget
<table>
#foreach (var item in Model.EntitiesList)
{
<tr>
<td> #Html.DisplayFor(modelItem => item.product_number) </td>
<td> #Html.DisplayFor(modelItem => item.product_name) </td>
<td> #Html.DisplayFor(modelItem => item.product_description) </td>
</tr>
}
</table>
#model Fruterias.Comun.Widget.IWidget
#foreach (Proyect.Comun.Widget.IWidget wm in ViewBag.Widgets)
{
#Html.Partial(string.Concat(new[] { "Widget", "/", "_Widget" }), wm)
}
then in the Dashboard controller:
public ActionResult Index()
{
ViewBag.Widgets = GetWidgetData();
return View();
}
public List<IWidget> GetWidgetData()
{
var lastWidget = new List<IWidget>{
new Widget()
{
SortOrder = 1,
CssClassName = "high",
Entity = "Products",
HeaderText = "Last Products",
FooterText = "",
SubWidget = new SubWidget {
EntitiesList = db.products.OrderByDescending(p => p.date).Take(10).ToList(),
}
},
};
return lastWidget;
}
And finally in the view for Dashboard/Index:
<p>
#{
#Html.Partial("Widget/_WidgetContainer");
}
</p>
This works ok and shows a list of Product entities. But now I want to create different widgets associated to different entities.
Of course the problem is that the property EntitiesList is declared as a collection of Product objects, so I can not fill it with, for example, customers objects.
What would be the solution here? I could create different interfaces (and classes) for each type of entity, but Im sure there must be a better way...
Also, as the entities models (Products, Customers...) are generated with Entity Framework db first, I guess I can not create an Interface and make them implement that interface (or can I?)... (anytime the db changes and models are regenerated by EF, all that would be lost?)
If you don't need to have the EntitiesList to be a specific type you could just have the SubWidget be generic and set its type when you instantiate.
public class SubWidget<T> : ISubWidget<T> where T : class
{
public ICollection<T> EntitiesList { get; set; }
}
or you could use dynamic object.
public class SubWidget : ISubWidget
{
public ICollection<dynamic> EntitiesList { get; set; }
}

How to Achieve model binding for Complex types

My model is :
public class ContactInfo
{
public IEnumerable<SupplierContact> PriceRequest { get; set; }
public IEnumerable<SupplierContact> OrderConfirmation { get; set; }
public IEnumerable<SupplierContact> Account { get; set; }
}
public class SupplierContact
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Title { get; set; }
public string Email { get; set; }
public string MobilePhone { get; set; }
}
and my Controller action is
public ActionResult EditContactInfo(ContactInfo contactInfo)
{
// not getting any values here..
}
View is rendering like :
#foreach (SupplierContact PriceRequest in Model.PriceRequest)
{
<tr class="">
<td style="text-align: left;" class="csstd-left">#Html.TextBoxFor(m => PriceRequest.Email)</td>
<td class="csstd">#Html.TextBoxFor(m => PriceRequest.MobilePhone)</td>
<td class="csstd">#PriceRequest.Title</td>
<td class="csstd">#PriceRequest.FirstName</td>
<td class="csstd">#PriceRequest.LastName</td>
</tr>
}
And I am referencing #model ContactInfo in my view
However i can achieve it using
Request.Form.Get("PriceRequest.Email")
but I want to use model binding feature .
You need to use a for loop (and you will need to change the collections from IEnumerable to IList to the name attributes are correctly indexed
#for (int i = 0; i < Model.PriceRequest.Count; i++) {
#Html.TextBoxFor(m => Model.PriceRequest[0].Email)
#Html.TextBoxFor(m => Model.PriceRequest[i].MobilePhone)
}
Alternatively you can create a EditorTemplate for SupplierContact and use
#Html.EditorFor(m => m.PriceRequest)
This will generate html like
<input name="PriceRequest[0].Email" ...
<input name="PriceRequest[0].MobilePhone" ...
<input name="PriceRequest[1].Email" ...
<input name="PriceRequest[2].MobilePhone" ...
etc.
Take a look at display and editor templates. Than you can create a view called SupplierContact. MVC automatically knows what to show if he see the complex type.
See this example:
http://www.asp.net/mvc/tutorials/javascript/using-the-html5-and-jquery-ui-datepicker-popup-calendar-with-aspnet-mvc/using-the-html5-and-jquery-ui-datepicker-popup-calendar-with-aspnet-mvc-part-2
So create a folder: DisplayTemplates in your views folder.
Then create a partial view called SupplierContact.
Set the model of the partial view as a SupplierContact.
Create the labels for displaying and run your application again.
For editing, create a EditorTemplates folder.

asp.net mvc binding between the model and the view

I am new to asp.net mvc . This is how my model looks like:
[Bind(Exclude = "JournalId")]
public class Journal
{
[ScaffoldColumn(false)]
public int JournalId { get; set; }
[DisplayName("Customer")]
public int CustomerId { get; set; }
[DisplayName("Till")]
public int TillId { get; set; }
[Required(ErrorMessage = "A Journal name is required")]
[StringLength(160)]
public string Name { get; set; }
[DisplayName("Journal creation date")]
public DateTime Date { get; set; }
[DisplayName("Journal creation time")]
public DateTime Time { get; set; }
public virtual Customer Customer { get; set; }
public virtual Till Till { get; set; }
}
[Bind(Exclude = "CustomerId")]
public class Customer
{
[ScaffoldColumn(false)]
public int CustomerId { get; set; }
[Required(ErrorMessage = "A customer name is required")]
[StringLength(160)]
public string Name { get; set; }
[StringLength(250)]
public string Address { get; set; }
}
[Bind(Exclude = "TillId")]
public class Till
{
[ScaffoldColumn(false)]
public int TillId { get; set; }
[Required(ErrorMessage = "A till no is required")]
[StringLength(160)]
public string TillNo { get; set; }
[StringLength(100)]
public string TillOperator { get; set; }
}
This is how my one of my controller's action is defined:
public ViewResult Index()
{
var journals = db.Journals.AsEnumerable<Journal>();
ViewData["journals"] = journals;
return View();
}
and the view :
#model IEnumerable<ErikDemo.Models.Journal>
#foreach (var item in (IEnumerable<ErikDemo.Models.Journal>)ViewData["journals"]) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Customer.Name)
</td>
<td>
#Truncate(item.Till.TillNo, 25)
</td>
<td>
#Truncate(item.Name, 25)
</td>
<td>
#Html.DisplayFor(modelItem => item.Date)
</td>
<td>
#Html.DisplayFor(modelItem => item.Time)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.JournalId }) |
#Html.ActionLink("Details", "Details", new { id=item.JournalId }) |
#Html.ActionLink("Delete", "Delete", new { id=item.JournalId })
</td>
</tr>
Although when I am debugging I can see in the controller that the list passed to the View is not empty, and also I see that the ViewData["journals"].Local in a watch is not empty, nothing gets displayed. I have also used the View.Model and return View(journals.ToList()) to send data to the View, but nothing seems to work. What is the issue here? Been on that half a day.
This is wrong: (Well it can be done like this, but I think you want to pass a model)
public ViewResult Index()
{
var journals = db.Journals.AsEnumerable<Journal>();
ViewData["journals"] = journals;
return View();
}
Try this:
public ViewResult Index()
{
var journals = db.Journals.AsEnumerable<Journal>();
return View(journals); //You just passed journals as a model
}
Also if you are using mvc 3 you can use ViewBag instead of ViewData
Example:
ViewData["Journal"] = "my string";
is the same as
ViewBag.Journal = "my string";
The ViewBag is dynamic, so you can use dot notation.
Additionally
This code:
#model IEnumerable<ErikDemo.Models.Journal>
#foreach (var item in (IEnumerable<ErikDemo.Models.Journal>)ViewData["journals"])
Should be like this:
#model IEnumerable<ErikDemo.Models.Journal>
#foreach (var item in Model)
Update:
I'm not sure what you're doing with this db.Journals.AsEnumerable<Journal>();
You should have a method somewhere that gets data from a table or table(s) and returns Journals. So lets say this all comes from one table in a database:
public class JournalViewModel
{
public IEnumerable<Journals> GetJournals()
{
using(var db = new ErikDataContext())
{
return db.Journals.ToList();
}
}
}
Then in the action:
public ViewResult Index()
{
var journals = new JournalsViewModel.GetJournals();
return View(journals); //You just passed journals as a model
}
Did you forget the <table> tag? If you haven't viewed the source of your page as it is rendered, I would recommend that you do this as a next step.

Categories