I know that If I want to see data from just one table in my Index View, I have to do this:
public class LocalidadesController : Controller
{
// GET: /Localidades/
private Entities db = new Entities();
//
// GET: /Concessao/
[Authorize(Roles = "ADMINISTRADOR")]
public ActionResult Index()
{
return View(db.SINCO_LOCALIDADE_CONCESSAO.ToList());
}
For two tables (in my case, views), I'm doing the changes below (localidades_view and municipios_view are the
views that I want to select data).
Model:
namespace SINCO_MVC.Models
{
[MetadataType(typeof(SincoLocalidadeConcessaoMetaData))]
public partial class SINCO_LOCALIDADE_CONCESSAO
{
}
public class SincoLocalidadeConcessaoMetaData
{
[Display(Name = "ID LOCALIDADE:")]
public int[] IDLOCALIDADE { get; set; }
[Display(Name = "ID:")]
public int IDCONCESSAO { get; set; }
[Display(Name = "Localidade:")]
public virtual LOCALIDADES_VIEW LOCALIDADES_VIEW { get; set; }
public virtual MUNICIPIOS_VIEW MUNICIPIOS_VIEW { get; set; }
}
}
View:
<%# Page Title="SINCO - Localidades" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<SINCO_MVC.Models.SINCO_LOCALIDADE_CONCESSAO>>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
SINCO - Localidades
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>SINCO - Localidades</h2>
<table>
<tr>
<th>
<%: Html.DisplayNameFor(model => model.IDCONCESSAO) %>
</th>
<th>
<%: Html.DisplayNameFor(model => model.IDLOCALIDADE) %>
</th>
<th></th>
</tr>
<% foreach (var item in Model) { %>
<tr>
<td>
<%: Html.DisplayFor(modelItem => item.MUNICIPIOS_VIEW.NOME_MUNICIPIO) %>
</td>
<td>
<%: Html.DisplayFor(modelItem => item.LOCALIDADES_VIEW.NOME_LOCALIDADE) %>
</td>
I did something like this, but it didn't work, because this fields in index stays empty.
How can I access the data of this views(oracle views)??
*Sorry for my bad english.
Make a ViewModel which contains two fields, one for each table, Done...something like
public class MyViewModel
{
public MyType Table1 {get;set;}
public MyType2 Table2 {get;set;}
}
The problem it was because of LazyLoad. I added the tables in my model but because of LazyLoad nothing returned. I had to add this code below in my index:
[Authorize(Roles = "ADMINISTRADOR")]
public ActionResult Index(SINCO_LOCALIDADE_CONCESSAO model)
{
return View("Index", db.SINCO_LOCALIDADE_CONCESSAO.Include(s => s.LOCALIDADES_VIEW).Include(s => s.MUNICIPIOS_VIEW));
}
Now it's working fine!
Related
I'm using paging with ASP.NET MVC, but I'm losing model data when navigating to next page.
Here is the code:
Partial view:
#using PagedList;
#using PagedList.Mvc;
#model Models.MyObject
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
<table class="table table-striped table-hover sortable">
<thead>
<tr>
<th width="240">#Model.HeaderNames[0]</th>
<th width="240">#Model.HeaderNames[1]</th>
<th width="240">#Model.HeaderNames[2]</th>
<th width="240">#Model.HeaderNames[3]</th>
<th width="120" class="no-sort"></th>
</tr>
</thead>
<tbody>
#foreach (var member in Model.PagedModelList)
{
<tr>
<td><span class="sort-field-value">#member.Thead1</span></td>
<td><span class="sort-field-value">#member.Thead2</span></td>
<td><span class="sort-field-value">#member.Thead3</span></td>
<td><span class="sort-field-value">#member.Thead4</span></td>
</tr>
}
</tbody>
</table>
<footer>
<div>
Page #(Model.PagedModelList.PageCount < Model.PagedModelList.PageNumber
? 0 : Model.PagedModelList.PageNumber) of #Model.PagedModelList.PageCount
#Html.PagedListPager(Model.PagedModelList, page =>Url.Action("Reports",new { #page = page, FirstLoad = false }))
</div>
</footer>
Controller :
public ActionResult Reports(MyObject model, int? page, bool FirstLoad = true)
{
model.pageSize = 4;
model.pageNumber = (page ?? 1);
if (FirstLoad)
{
// getting the data from database here
// ... code
// assigning pagemodelist
model.PagedModelList = model.ModelList.ToPagedList(model.pageNumber, model.pageSize);
}
// here sending the model and all is good
return PartialView("_MyView", model);
}
Model
public class MyObject
{
public int SelectedPeriod { get; set; }
public List<SecondObject> ModelList = new List<Secondobject>();
public IPagedList<Secondobject> PagedModelList ;
public int pageSize { get; set; }
public int pageNumber { get; set; }
}
Second model class:
public class SecondObject
{
public string Thead1 { get; set; }
public string Thead2 { get; set; }
public string Thead3 { get; set; }
public string Thead4 { get; set; }
}
Expected to get next page but all I get is empty model which causes null reference when sending again to view from controller. What am I doing wrong here?
I'm getting right data in model the first time, I show the table with correct data, then when clicking on next page I debug in the controller so I got empty model.PagedModelList, even some other empty model properties .
Any help appreciated
Maybe, try to pass your model in parameters like :
#Html.PagedListPager(Model.PagedModelList, page =>Url.Action("Reports",new {#model = Model, #page = page, FirstLoad = false }))
Edit :
Another solution is to remove MyObject from parameters.
Load each time your data from your database. You can follow the example in
GitHub project
I have School, Teachers and Qualifications tables in my database. Teacher table refs qualificationid and schoolid in Qualification and Schools table.
I'm not using Entity Framework and I have DB-connection class to do CLUED operations.
In my Teacher class
public int TeacherID { get; set; }
public string Name { get; set; }
public string NIC { get; set; }
public string Address { get; set; }
public int Telephone { get; set; }
public Nullable<int> SchoolID { get; set; }
public Nullable<int> QualificationID { get; set; }
public virtual Qualifications Qualifications { get; set; }
public virtual Schools Schools { get; set; }
My schools class
public int SchoolID { get; set; }
public string Name { get; set; }
public int Telephone { get; set; }
public string Address { get; set; }
public virtual ICollection<Teachers> Teachers { get; set; }
My Qualification class
public int QualificationID { get; set; }
public string Type { get; set; }
public virtual ICollection<Teachers> Teachers { get; set; }
My DBConnection class
public List<Teachers> getAllTeachers()
{
List<Teachers> teachersdata=new List<Teachers>();
string connection = Connection.ConnectionString;
SqlConnection con = new SqlConnection(connection);
con.Open();
SqlCommand cmd = con.CreateCommand();
cmd.CommandText = "Select * from Teachers as T,Qualifications as Q,Schools as S where S.SchoolID=T.SchoolID and T.QualificationID=Q.QualificationID";
SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.KeyInfo);
while(dr.Read())
{
Teachers teacher = new Teachers();
teacher.TeacherID = dr.GetInt32(0);
teacher.Name = dr.GetString(1);
teacher.NIC = dr.GetString(2);
teacher.Address = dr.GetString(3);
teacher.Telephone = dr.GetInt32(4);
teacher.SchoolID = dr.GetInt32(5);
teacher.QualificationID = dr.GetInt32(6);
teacher.Qualifications.QualificationID = (Int32)dr["QualificationID"];
teacher.Qualifications.Type =(string) dr["Type"];
teacher.Schools.SchoolID = (Int32)dr["SchoolID"];
teacher.Schools.Name = (string)dr["Name"];
teacher.Schools.Telephone = (Int32)dr["Telephone"];
teacher.Schools.Address = (string)dr["Address"];
teachersdata.Add(teacher);
}
return teachersdata;
}
in teachersController
public ActionResult Index()
{
List<Teachers> allTeachers = _db.getAllTeachers();
return View(allTeachers);
}
at last in index.aspx i have
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MyLayer.Teachers>>" %>
<!DOCTYPE html>
<html>
<head runat="server">
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<p>
<%: Html.ActionLink("Create New", "Create") %>
</p>
<table>
<tr>
<th>
<%: Html.DisplayNameFor(model => model.TeacherID) %>
</th>
<th>
<%: Html.DisplayNameFor(model => model.Name) %>
</th>
<th>
<%: Html.DisplayNameFor(model => model.NIC) %>
</th>
<th>
<%: Html.DisplayNameFor(model => model.Address) %>
</th>
<th>
<%: Html.DisplayNameFor(model => model.Telephone) %>
</th>
<th>
<%: Html.DisplayNameFor(model => model.Schools.Name) %>
</th>
<th>
<%: Html.DisplayNameFor(model => model.Qualifications.Type) %>
</th>
<th></th>
</tr>
<% foreach (var item in Model) { %>
<tr>
<td>
<%: Html.DisplayFor(modelItem => item.TeacherID) %>
</td>
<td>
<%: Html.DisplayFor(modelItem => item.Name) %>
</td>
<td>
<%: Html.DisplayFor(modelItem => item.NIC) %>
</td>
<td>
<%: Html.DisplayFor(modelItem => item.Address) %>
</td>
<td>
<%: Html.DisplayFor(modelItem => item.Telephone) %>
</td>
<td>
<%: Html.DisplayFor(modelItem => item.Schools.Name) %>
</td>
<td>
<%: Html.DisplayFor(modelItem => item.Qualifications.Type) %>
</td>
<td>
<%: Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) %> |
<%: Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) %> |
<%: Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ }) %>
</td>
</tr>
<% } %>
</table>
</body>
</html>
But when I run the project i got this error Object reference not set to an instance of an object in dbconnnection class teacher.Qualifications.QualificationID = (Int32)dr["QualificationID"]; .how can i fix this?
I did a LINQPad program with this code
void Main()
{
Teachers teacher = new Teachers();
teacher.TeacherID = 12;
teacher.Name = "Jones";
teacher.Qualifications.QualificationID = 7;
teacher.Dump();
}
This is similar to the part you have in your loop. The problem is that teacher.Qualifications expects an instance of an object. But you did not create one. In your line teacher.Qualifications.QualificationID you are trying to assign a value to the non-static property QualificationID.
You could write
var qual = new Qualifications();
qual.QualificationID = 7;
teacher.Qualifications = qual;
Please let me know if you need more help.
I am new in MVC and learning MVC. Now I do not want to use any grid extension, rather I want to generate tabular UI just by HTML table. So I was looking for code and found a hint.
This code is not full code. Here is what I got.
<% if (Model.Count() > 0)
{ %>
<table width="35%">
<thead><tr><th>Species</th><th>Length</th></tr></thead>
<% foreach (var item in Model)
{ %>
<tr>
<td><%= item.FishSpecies%></td>
<td align="center"><%=item.Length%></td>
</tr>
<% } %>
</table>
<% }
else
{ %>
No fish collected.
<%} %>
The problem is I am not being able to visualize how the model class should look like and how it is populated from controller. Viewbag is not used in code, rather generating table directly from model class.
So can anyone write a small complete code for me just to create a HTML table and populate with model directly without using viewbag?
Need code for model, controller and view too.
Your model actually needs to be a IEnumerable<Model>. So you might have a model:
public class Model
{
public string FishSpecies { get; set; }
public int Length { get; set; }
public static IEnumerable<Model> Load() { ... }
}
and then in your controller's action:
var list = Model.Load();
return View(list);
and then in the view you need to define the model at the very top:
#model System.Collections.IEnumerable<My.Namespace.Model>
Now, these two lines aren't going to work:
<td><%= item.FishSpecies%></td>
<td align="center"><%=item.Length%></td>
they need to be something more like this:
<td>#Html.DisplayFor(m => item.FishSpecies)</td>
<td>#Html.DisplayFor(m => item.Length)</td>
If you want to iterate through your model and create your table, first of all change the #model of your view like this:
#model IEnumerable<myPrj.Models.EntityName>
Then, you should change your action method to supply model items to your view:
public ActionResult Index()
{
return View(db.EntityNames.ToList());
}
and finally, iterate your model and create your table:
<table id="tblNews">
<tr>
<th>
#Html.DisplayNameFor(model => model.Property1)
</th>
// ...
<th>
#Html.DisplayNameFor(model => model.Propertyn)
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Property1)
</td>
// ...
<td>
#Html.DisplayFor(modelItem => item.Propertyn)
</td>
</tr>
}
</table>
and about the model? Model is nothing but a class with some properties:
public class MyModel
{
[Display(Name = "Property 1")]
[Required(ErrorMessage = "Property cannot be empty")]
public int Property1 { get; set; }
// ...
[Display(Name = "Property n")]
[Required(ErrorMessage = "Property cannot be empty")]
public string Propertyn { get; set; }
}
I am developing an ASP .Net MVC 3 application using C# and SQL Server 2005.
I am using also Entity Framework and Code First Method.
I have a view 'Application' which contain a DropDownList.
The DropDownList load its items from the table Genre in the base.
I would like to show a table of values and that using a list already defined in the model.
The values of table depends on the value of DropDownList.
I have always this error :
Object reference not set to an instance of an object.
Description: An unhandled exception occurred during the execution of
the current web request. Please review the stack trace for more
information about the error and where it originated in the code.
This is the code of my view :
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcApplication2.Models.FlowViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Application
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Application</h2>
<form id="form1" runat="server">
<h2><%= Html.Encode(ViewData["Message"]) %> </h2>
<div>
<%:Html.Label("Type :")%><%: Html.DropDownListFor(model => model.SelectedGenre, Model.GenreItems)%>
</div>
<table border = "transparent">
<tr>
<th>
</th>
</tr>
<% foreach (var item in Model.FaItems) { %>
<tr>
<td>
<%: Html.DisplayFor(modelItem => item.Nom_Famille) %>
</td>
</tr>
<% } %>
</table>
</form>
</asp:Content>
and this is the Controller :
[HttpGet]
public ActionResult Application(Genre genre)
{
var vv = new FlowViewModel();
vv.GenreItems = new SelectList(db.Genres.ToList(), "ID_G", "ID_G");
if (vv.SelectedGenre == "Famille")
{
vv.FaItems = db.Familles.ToList();
}
else if (vv.SelectedGenre == "Sous Famille")
{
vv.SFItems = db.Sous_Familles.ToList();
}
return View(vv);
}
and finally this is the model 'FlowViewModel' :
public class FlowViewModel
{
[Key]
public string IDv { get; set; }
public List<Famille> FaItems { get; set; }
public List<Sous_Famille> SFItems { get; set; }
[NotMapped]
public SelectList GenreItems { get; set; }
public string SelectedGenre { get; set; }
}
Stack Trace :
If this condition is false:
vv.SelectedGenre == "Famille"
You don't set a value to vv.FaItems and therefor as long as vv.SelectedGenre != "Famille", then vv.FaItems is null and will throw a NullReferenceException when trying to use foreach over it.
You can either add an else and put a new empty list, or wrap the foreach with an if (vv.FaItems != null) to avoid the exception.
Here is an alternative that will remove the need for duck-type checking.
public class FlowViewModel
{
[Key]
public string IDv { get; set; }
public List<Famille> FaItems { get; set; }
public List<Sous_Famille> SFItems { get; set; }
[NotMapped]
public SelectList GenreItems { get; set; }
public string SelectedGenre { get; set; }
public FlowViewModel()
{
FaItems = new List<Famille>();
SFItems = new List<Sous_Famille>();
}
}
I have a web app where I want to show a form for a Test object. Different Test instances can have different schemas. I can display this pretty nicely, but it won't populate all the data from the form back into my model.
Here are my model classes:
public class EnterTestData
{
public string StudyId { get; set; }
public Test Test { get; set; }
}
public sealed class Test
{
public string Identity { get; set; }
public string Name { get; set; }
public IEnumerable<TestField> Fields { get; set; }
}
public sealed class TestField
{
public string Identity { get; set; }
public string Name { get; set; }
public string Value { get; set; }
public string Type { get; set; }
}
Here is the relevant portion of my View:
<% Html.BeginForm("PostTestData", "StudiesUserInterface"); %>
<table>
<%
foreach (var testField in Model.Test.Fields)
Html.RenderPartial("UserControls/TestFieldUserControlascx", testField);
foreach (var category in Model.Test.Categories)
{
%>
<tr>
<td colspan="2" style="font-style: italic; text-align: center;">
<%=category.Name %>
</td>
</tr>
<%
foreach (var testField in category.Fields)
Html.RenderPartial("UserControls/TestFieldUserControlascx", testField);
}
%>
<tr>
<td colspan="2" style="text-align: right;">
<input type="submit" name="newsletter" value="Enter Result" />
</td>
</tr>
</table>
<% Html.EndForm(); %>
And the partial view for the actual text boxes:
<tr>
<td>
<%= Model.Name %>
</td>
<td>
<%
switch (Model.Type)
{
case "date":
case "text":
case "number":
%>
<%= Html.TextBox(Model.name, Model.Value) %>
<% break;
default: %><%= Html.Label("Unknown data type") %><% break;
}
%>
</td>
</tr>
Update Controller methods:
public ActionResult EnterTestData(string studyId, string testId)
{
var testDefinition = ServiceKitLocator.GetStudyService().GetTestDefinition(testId);
return View(new EnterTestData { StudyId = studyId, Test = testDefinition });
}
public ActionResult PostTestData(EnterTestData model)
{
//I'm just putting a break point here and checking the model in the debugger for now
return RedirectToAction("Index");
}
The problem is that Test is null when it comes back to my Controller. How do I get it to be populated? Why is it null?
I think the problem is the Html.TextBox element.
If it's correct that the model in your view is type of "Test" but in your controller action you want to bind to type of "EnterTestData" which has a property of type "Test" named "Test"
Then your TextBox should be initializied like
Html.TextBox("Test.Name", Model.Value)
The important part is the name parameter. The modelbinder matches this name with the properties of the model type in your post action, in your case "EnterTestData".
You can also use an editor template view. Which does the same as your partial view.
In your project go to Views\Shared\ and create a folder named EditorTemplates, if not exists.
In this folder create a partial view and name it like the class/type the template should be for. In your case "TestField.ascx". Actually you can copy and rename your existing partial view.
In you main view you have to change 2 things:
- use for instead of foreach
- call the editor template in the loops
like:
for(int i = 0; i < Model.Test.Fields.Count(); i++)
Html.EditorFor(Model => Model.Test.Fields[i]);
In the template view you have to change one thing:
- user TextBoxFor instead of TextBox
like:
Html.TextBoxFor(Model => Model.Value)
I use this pattern often. It makes it easy to bind complex models.
You may have a look at the generated HTML