ASP.NET MVC creating Model from Database (Postgres) - asp.net-mvc

Please forgive me if this question is too stupid but I just started learning ASP for few days...
So I decided to make some simple Web application which will dispaly data from database (Postgres).
To connect to DataBase I using NpgsqlConnection class. I saw few tutorials how to connect to DB i.e. here, but almoust everywhere they are using MSSQL and nowhere I cant find solutions for my case.
So I would like to have model which will be contains all fetched data within I will be able to iterate like this:
<% foreach (var item in Model)
{ %>
<tr>
<td><%: item.Title %></td>
<td><%: String.Format("{0:g}", item.ReleaseDate) %></td>
<td><%: item.Genre %></td>
<td><%: item.Rating %></td>
<td><%: String.Format("{0:F}", item.Price) %></td>
</tr>
<% } %>
So How I should do to achieve this?
I thought to create class
public class Person{
int id;
string Name;
string Surname;
...
}
next create generic List of type Person and after fetch data, add all fetched data to my List. And then somehow pass this List as Model.
I think there is some better way to do it right. Any Suggest?

Nope, you're pretty much on track.
The main difference you see from the tutorials is most of them are probably using entity framework to populate the models. Since you're using postgres...i wouldn't really recommend trying to get entity framework to work with it (I heard it's a nightmare). You can use a different Orm if you like, or just do it with your connection command and reader like you're probably used to.
The way I would do it is create a domain model that looks like just like the database model (looks like what you did with Person)
From there you would populate it in a Controller.
public class PersonController : Controller
{
//this method will map to the Person/Index route by default
public ActionResult Index()
{
//use your npgsqlconnection right now to populate whatever object you'd like
List<Person> people = PopulateFromPostgres();
//here were returning the index view with the model being a list of person
return View(people)
}
}
Then in your view (Views/Person/Index.cshtml i believe in this example)
#model List<Person>
<table>
#foreach (var item in Model)
{
<tr>
<td>#item.Title</td>
<td>#String.Format("{0:g}", item.ReleaseDate)</td>
<td>#item.Genre</td>
<td>#item.Rating </td>
<td>string.Format("{0:F}", item.Price)</td>
</tr>
}
</table>
Let me know if there's more specific area you don't understand here.

Related

How client data will deserialize to model class when form post in mvc

suppose i have model class look like
public class Person
{
[Required]
[MaxLength(50,ErrorMessage="Full name should be within 50 character")]
public string full_name { get; set; }
[Range(18,80)]
[Required(ErrorMessage="Please provide age")]
public Int32 Age { get; set; }
}
and i have form based on this model class
#{Html.BeginForm("PostData", "Customodelbinder");
<table>
<tr>
<td>First Name : </td>
<td>#Html.TextBox("first_name")</td>
</tr>
<tr>
<td>Middle Name : </td>
<td>#Html.TextBox("middle_name")</td>
</tr>
<tr>
<td>Surname :</td>
<td> #Html.TextBox("last_name")</td>
</tr>
<tr>
<td>Age:</td>
<td> #Html.TextBox("age") </td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" name="Save" value="Save" />
</td>
</tr>
</table>
}
now i like to know when i will submit the form then PostData will be called and how data will automatically posted to Person model class from client side to server side
public void PostData(Person person)
{
}
i search google and found we need to use ModelBinder is it true ? when one should use ModelBinder ?
http://www.codeproject.com/Tips/806415/Model-Binding-using-IModelBinder-and-DefaultModelB
without using ModelBinder can't we post client side data to action method where action method will have person argument and automatically client side person data will be de-serialize to person class ??
please help me how to do it with & without model binder with some sample code. thanks
i search google and found we need to use ModelBinder is it true ?
Partially, DefaultModelBinder does work well in most case where primitive and even complex types involved. So you don't need to consider writing ModelBinder in most cases. I have 6-8 controller and 150+ action and need not written a single binder.
when one should use ModelBinder ?
When the DefaultModelBinder is failing to bind your request data into the model. e.g. you are getting a request from a device that has typical format, security key, data, etc. DefaultModelBinder works on best case match i.e. it will look into you request params and try to find exact name in model, if a match is find, it will copy value in model.
without using ModelBinder can't we post client side data to action method where action method will have person argument and automatically client side person data will be de-serialize to person class ??
Sure you can, we all do that. Using AJAX post method. Pass the model data into the data property in ajax request. If you name your js model correctly, the data will be bind to controller action parameter perfectly. e.g.
var searchResultModel = { searchId: searchId, isSearchEdited: true };
// Get the result view
$.ajax({
url: '#Url.Action("SearchResult", "Search")',
contentType: 'application/json; charset=utf-8',
type: 'POST',
dataType: 'html',
data: JSON.stringify(searchResultModel)
})
.success(function (searchResult) {
$('#contentLoader').html(searchResult);
});

Left join with Code First MVC 4 EF4.1

I'm creating a system where users have some setting to do to complete their account, see below :
Tables:
SettingsTypes
Id
Name
Settings
Id
FkSettingTypeId
IsEmailActivated
IsSMSActivated
IntervalNotification
So the SettingsType table have these kind of value :
Be warned if time almost over
Be warned about offers in my categories
...
Back into my MVC4 application I need to create a controller that will return every SettingsType with Setting to get a html table where user can choose if he want receive an email and sms for each SettingsType.
I use the Entity Framework 4.1 with CodeFirst and an ordinary page will return the table object like this :
public ActionResult Index()
{
var settings = db.Settings.Include(s => s.SettingsType);
return View(settings.ToList());
}
The include statement make an inner join and do not return all the SettingsType I need associated with the Setting.
How can I write my code to do a left or right join and get the right model to pass into my views like that :
#model IEnumerable<TenderSystem.Models.Setting>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.SettingsType.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.IsEmailActivated)
</td>
<td>
#Html.DisplayFor(modelItem => item.IsSMSActivated)
</td>
<td>
#Html.DisplayFor(modelItem => item.IntervalNotification)
</td>
</tr>}
I tried many thing like these link :
Entity Framework Code First Left Join
Fluent API Samples
But I can't achieve what I expect for.
To conclude, I also use the SQL to LINQ converter tool to convert my very easy SQL left join into LINQ and may be return the object I can use into my view but I got this error : Only parameterless constructors and initializers are supported in LINQ to Entities.
Need your help to understand the right thing to do with this situation.
Thank you very much
I think the Include can just be the child's model name as a string under one of the constuctors. Here is a link for EF5.
http://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=EN-US&k=k("System.Data.Entity.Infrastructure.DbQuery`1.Include");k(Include);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5);k(DevLang-csharp)&rd=true
or shortened...
http://bit.ly/SOEttF
I am using WebAPI so the return wants an IQueryable and this works for me.
[AcceptVerbs("GET")]
public IQueryable<Run> Runs()
{
var rx = _contextProvider.Context.Runs
.Include("RunOutlineItems")
.AsQueryable()
.Where(r => r.RunStatusId < 4);
return rx;
}
also check this answer
Join and Include in Entity Framework

asp.net mvc - pass partial data model to partial view

I wish to build a partial view that gets a model column and print it.
Something like that:
At the view:
#model IEnumerable<products_comparison.Models.Product>
#{
ViewBag.Title = "Index";
var Brand = (from r in Model
select r.Brand).Distinct();
}
<h2>
Index</h2>
#Html.RenderPartial("_DisplayAttribute",Brand)
And at the partial view:
<table>
<tr>
<th>
Brand
</th>
</tr>
#foreach (var row in Model)
{
<tr>
<td>
#Html.DisplayFor(r => row)
</td>
</tr>
}
</table>
There are a few problems I run into:
The compiler doesnt allow me to send Barnd to the partial view.
If you look at the partial view code you will see the word Brand, which is the column name. I dont wish to hard-coded the word "Brand" in the partial view, instead I like that the column name will be there.
In the partial view I need to put #model products_comparison.Models.Product, but I dont
want to send the hole table. I want to send only one column - But I dont know what to put there..
Thanks!
EDIT:
Just to clear one thing, I want that the view will call the same partial view for each column in the table(for most of the columns in the table anyway) and each time I'll send a different column(distinct value column to be exact).
Start by refactoring and putting the right logic into the right place. This LINQ query has strictly nothing to do in a view. A view is not supposed to do any LINQ queries or whatever to pull data. A view is supposed to work with data that it is passed to it from the controller action under the form of a view model. A controller action builds and passes an adapted view model that you define for the view.
So as always you start by defining a view model that will be adapted to the requirements of your view:
public class MyViewModel
{
public IEnumerable<Brand> Brands { get; set; }
}
then you write a controller action that will populate this view model and pass it to the view:
public ActionResult Foo()
{
IEnumerable<products_comparison.Models.Product> products = ...
var model = new MyViewModel
{
Brands = (from r in Model select r.Brand).Distinct()
};
return View(model);
}
then a view:
#model MyViewModel
<table>
<tr>
<th>
Brand
</th>
</tr>
#Html.DisplayFor(x => x.Brands)
</table>
and finally you could define a corresponding display template which will automatically be rendered for each element of the Brands collection of your view model (~/Views/Shared/DisplayTemplates/Brand.cshtml):
#model Brand
<tr>
<td>
#Html.DisplayForModel()
</td>
</tr>
For 1 try changing #Html.RenderPartial("_DisplayAttribute",Brand) to #Html.Partial("_DisplayAttribute",Brand)
You will also need to specify the model in the partial view like #model products_comparison.Models.Brand or something like it
Also please clarify 2 & 3 as they are not clear what you want

How to access the Model from the View?

I have a search page that display a search result. The search result is a list of persons that matched the specific search. I'm iterating through this list displaying them in a table. As headers for this table I want the DisplayName from the model. If I don't inherit IEnumerable I wouldn't be able to iterate through the list. I'm new at this MVC thing =)
I iterate through the result like this:
<% foreach (var item in Person) { %>
<%: item.surname %>
<% } %>
But how do I print the "DisplayName" of an attribute without iterating through the whole list? I would just like to do:
<%: Html.LabelFor(m => m.surname) %>
If it's any help I inherit an IEnumerable at the top of the page:
<%# Page Inherits="System.Web.Mvc.ViewPage<IEnumerable<RegistryTest.Models.Person>>" %>
Edit
I want to display "Your surname" but I don't know how to access it from the view.
[DisplayName("Your surname")]
public object surname { get; set; }
Here's a very similar question that hasn't been answered either: Can I use LabelFor() when the page inherits from IEnumerable<T>?
If you only need to display specifics of one person; you should consider sending only one person to the view instead of a complete list of persons. In that case
Model.Surname
would work just like that. So instead of:
Inherits="System.Web.Mvc.ViewPage<IEnumerable<RegistryTest.Models.Person>>"
do
Inherits="System.Web.Mvc.ViewPage<RegistryTest.Models.Person>"
In this case a single person is loaded into your Model and Model.Property works fine. If you want an IENumerable<>, think about what that means. You are sending a list of persons, so the only thing in your "Model" is a IENumerable<> of persons. There is no way that the view can know what you want if you call Model.Property, since in the Model there are multiple Objects and the view doesn't know which Object you want to get the Property from.
Bottom line, if you want to call Model.Property (Model.surname) but also want to send an IENumerable you are having a design flaw. If you send a list you should want to do something with the complete list (iterate through and do something with the contents). If you just want to do something with one person in that list, re-design your view/controller and send that single person; then you can use Model.Property.
//EDIT BASED UPON COMMENTS
As I see it now you either want to do one of those two things (I do not know which):
Show the records of an item in your list in a table and put the DisplayName of the current object shown in the table in the header.
Show all items of the list in your table and put some sort of DisplayName in the header. This makes less sence but it could be that you mean to name your list.
Situation 1
This is working as the rest of your code? The following would work just fine.
<% foreach (var item in Model) { %>
<table>
<th>item.DisplayName</th>
<tr>
<td>item.Property1</td>
<td>item.Property2</td>
</tr>
</table>
<% } %>
Situation 2
If you want a DisplayName of the list (??) you should create a ViewModel containing the IENumerable of Persons and a public string ListName. Now you can do something like:
<table>
<th>Model.ListName</th>
<% foreach (var item in Model) { %>
<tr>
<td>item.Property1</td>
<td>item.Property2</td>
</tr>
<% } %>
</table>
this would create a table with the name of your List (given in the ViewModel) as header and as items in the table you have your persons.
Design problem?
However, I would love to see you write some more information in your question above. Give us some more information on what you want to do. Do you want to show records of each Person in the list one-by-one? In that case I would recommend you create a Partial View where you put your table. Then you would get something like:
<% foreach (var item in Model) { %>
<% Html.RenderPartial("TablePerson",item); %>
<% } %>
tableperson.ascx:
...
Inherits="System.Web.Mvc.ViewPage<IEnumerable<RegistryTest.Models.Person>>"
...
<table>
<th>Model.DisplayName</th>
<tr>
<td>Model.Property1</td>
<td>Model.Property2</td>
</tr>
</table>
So, we need more information I'm afraid :)
If it's a collection with every entry having the same surname then try model[0].surname or model.ToList().First().surname
You don't need ToList() if its a List<T> already. Then it would be just model.First()
You are specifying that the page model is IEnumerable, and you say you would like to print a property of an element. Since you have a list of elements, you need to specify which of the elements you would like to retrieve the property from.
I you want a specific index in the list you will need to convert the IEnumerable collection to IList (ToList()), depending on the criteria, you may also be able to find the required element using something like a LINQ Single() operation.
Otherwise you could select the property from all the element in the list using Model.Select(m => m.PropertyName) which will give you a list of just this property, and then concatenate this list to a single string.

ASP.Net MVC: Html.Display() for object in a Collection

The standard MVC example to draw an item with the appropriate View Template is:
Html.DisplayFor(m => m.Date)
If the Model object has a property named Date of type DateTime, this returns a string with the HTML from the Display/DateTime.ascx template.
Suppose you wanted to do the same thing, but couldn't use the strongly-typed version - you didn't know the Model's type for this View at compile time. You use the older:
Html.Display("Date");
So here's the hard part.
Suppose the Model is IEnumerable. You don't know what those objects are at compile-time, but at run-time they happen to be objects with a Date of type DateTime again, like:
public class ModelClass
{
public DateTime Date { get; set; }
}
Now suppose you want your View to iterate over those objects and render each out. If all you cared about was the value you could do this:
<%
StringBuilder sb = new StringBuilder();
foreach(object obj in (IEnumerable<object>)Model)
{
Type type = obj.GetType();
foreach(PropertyInfo prop in type.GetProperties())
{
// TODO: Draw the appropriate Display PartialView/Template instead
sb.AppendLine(prop.GetValue(obj, null).ToString());
}
}
%>
<%= sb.ToString() %>
I'm obviously taking some shortcuts to keep this example focused.
Here's the point - how do I fulfill that TODO I've written for myself? I don't just want to get the value - I want to get it nicely formatted like Html.Display("Date"). But if I just call Html.Display("Date"), it inspects the Model, which is an IEnumerable, for a property named Date, which it of course does not have. Html.Display doesn't take an object as an argument to use as the Model (like Html.Display(obj, "Date"), and all the classes and methods I can find that lie underneath appear to be internal so I can't tweak and call into them directly.
There must be some simple way to accomplish what I'm trying to do, but I can't seem to find it.
Just to make sure I'm being clear - here's an example of the code of DateTime.ascx:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.DateTime>" %>
<%= Model.ToString("MM/dd/yyyy") %>
And so, ideally, the output from this View that can take any Model, but in this case a list of 3 of these ModelClass objects above, would be:
11/10/2001
11/10/2002
11/10/2003
Because the code would find the Display PartialView for DateTime and render it appropriately for each.
So - how do I fulfill the TODO?
Have a look at the template code in this excellent post from Phil Haack. It seems to come close to what you are looking for: http://haacked.com/archive/2010/05/05/asp-net-mvc-tabular-display-template.aspx
I've found one potential solution to this but I'm not in love with it; it requires using several file-based templates, meaning you can't abstract this easily into a code library for use in multiple projects.
The View:
<%
StringBuilder sb = new StringBuilder();
Type itemType = Model.GetType().GetGenericArguments()[0];
sb.AppendLine("<table>");
// Pass in the Model (IEnumerable<object>)'s generic item type as
// the Model for a PartialView that draws the header
sb.Append(Html.Partial("DisplayTableHead", itemType));
foreach(object item in (IEnumerable<object>)Model)
{
sb.Append(Html.Partial("DisplayTableRow", item));
}
sb.AppendLine("</table>");
%>
<%= sb.ToString() %>
Views/Shared/DisplayTableHead.ascx:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Type>" %>
<tr>
<%
foreach (PropertyInfo prop in Model.GetProperties())
{
%>
<th><%= prop.Name %></th>
<%
}
%>
</tr>
Views/Shared/DisplayTableRow.ascx:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<tr>
<%
Type modelType = Model.GetType();
foreach (PropertyInfo modelField in modelType.GetProperties())
{
%>
<td><%= Html.Display(modelField.Name) %></td>
<%
}
%>
</tr>
But I now see the major flaw in this solution, which is that Clicktricity's posted solution acknowledges details in the ModelMetadata - like whether that particular property is set for display, whether it's complex or not, etc.

Resources