ASP.net mvc in new for me, for some time I used php (no mvc), but now i'm interested, how I can fetch one row from db? without foreach, for example in title...
here is some code:
controller
public ActionResult Index()
{
var pages = (from page in db.Pages where page.PageName == "index" select page).ToList();
return View(pages);
}
view:
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
<% foreach (var item in Model)
{ %>
<%= Html.Encode(item.Text) %>
<% }
%>
</asp:Content>
In your controller, instead of .ToList() you can use the .FirstOrDefault() method, this will return only the first row from the database.
Then in your view you won't need the foreach.
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
<%= Html.Encode(item.Model.Text) %>
</asp:Content>
What you're doing there is creating a List datatype variable and passing it in as the Model to your view. Assuming this is the only piece of data your page needs. Here's what you would do;
public ActionResult Index()
{
string page = db.pages.where(p => p.PageName == "index").FirstOrDefault().PageName;
return View(page);
}
There in your page, Model will now be that single string value and you can do this;
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
<%= Model %>
</asp:Content>
Although it is best practice to create a ViewModel for the page with the just the properties your page will need and pass that in as the Model.
public class MypageViewModel
{
public string PageName { get; set; }
}
Then do this in the controller
public ActionResult Index()
{
MypageViewModel MyModel = new MypageViewModel();
MyModel.PageName = db.pages.where(p => p.PageName == "index").FirstOrDefault().PageName;
return View(MypageViewModel);
}
Hope that helps.
If you are using Entity Framework:
var singleItem = db.pages.Find(id);
This will use the Primary Key of your entity.
If you have a composite primary key consisting of multiple properties, Find will still work (because it can take multiple values):
var singleItem = db.pages.Find(key1, key2);
Related
just trying to fathom out LINQ to SQL and datacontext class.
I am learning MVC coding and have a database with some test data.
I have created my datacontext and have been able to get this far in the controller.
ClientClassesDataContext context2 = new ClientClassesDataContext();
var result2 = context2.up_GetClient(4,1);
up_GetClientResult myObject = result2.SingleOrDefault();
return View(myObject);
This returns a list of clients, my part I'm stuck at is how to pass this to the view and put it in a grid style.
Even passing the object to the view with only one row of data, I'm kinda stuck on how t even access items and display in, say, a text box.
Even just any pointers or links on best practice for LINQ to SQL etc would be a great help. There seems to be a lot of varying info out there.
The View is empty with the code below.
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Test</h2>
</asp:Content>
Any help or pointers would be appreciated.
Model:
public class MyModel
{
IEnumerable<client> _getClient { get; set; }
}
Controller:
ClientClassesDataContext context2 = new ClientClassesDataContext();
var result2 = context2.up_GetClient(4,1);
MyModel _mymdl=new MyModel();
_mymdl._getClient = result2.SingleOrDefault();
return View(_mymdl);
VIew:
#model ProjectName.web.MyModel
#{
ViewBag.Title = "";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div>
foreach (var item in Model._getClient)
{
//Add your login to create Table
}
</div>
I have the following MVC2 view that is strongly typed with a viewmodel, the viewmodel contains a list of values from one db table, I need to display a single value from a second table in the view, this is my view code
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<CustomerDatabase.WebUI.Models.CustomerSitesListViewModel> " %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Customer Sites
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<% foreach (var customerSite in Model.CustomerSites) { %>
<% Html.RenderPartial("CustomerSiteSummary", customerSite); %>
<%} %>
</asp:Content>
This is the viewmodel, notice i am including a Customer member in the viewmodel as i want to display the customer name in addition to the list of customer sites
namespace CustomerDatabase.WebUI.Models
{
public class CustomerSitesListViewModel
{
public IList<CustomerSite> CustomerSites { get; set; }
public PagingInfo PagingInfo { get; set; }
public Customer customer { get; set; }
}
}
This is my controller code for the view
public ViewResult List([DefaultValue(1)] int page)
{
var customerSitesToShow = customerSiteRepository.CustomerSites;
var viewModel = new CustomerSitesListViewModel
{
CustomerSites = customerSitesToShow.Skip((page - 1) * PageSize).Take(PageSize).ToList(),
PagingInfo = new PagingInfo
{
CurrentPage = page,
ItemsPerPage = PageSize,
TotalItems = customerSitesToShow.Count()
}
};
return View(viewModel); //Passed to view as ViewData.Model (or simply model)
}
This is my partial view that renders the list,
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<CustomerDatabase.Domain.Entities.CustomerSite>" %>
<div class="item">
<div class="customer-list-item">
<h2><%:Model.customer.CustomerName%></h2>
<%: Model.AddressLine1 %>
<%: Model.AddressLine2%>
Although intellisense lets me access the customer object from the view with
<h2><%:Model.customer.CustomerName%></h2>
An error is thrown when i navigate to the view,
Object reference not set to an instance of an object.
Source Error:
Line 7: <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
Line 8: <% foreach (var customerSite in Model.CustomerSites) { %>
Line 9: <%:Model.customer.CustomerName%>
Line 10: <% Html.RenderPartial("CustomerSiteSummary", customerSite); %>
Line 11: <%}
I think the error is due to the view rendering a list, i tried changing the viewmodel member to
public IList<Customer> {get; set;}
but this doesn't work either.
Can anyone suggest a way i can achieve this or offer any advice on where i am going wrong this is one problem i haven't been able to resolve after hours or researching on the Internet?
It looks like one of the model properties are not initialized. If you add a breakpoint on that line and check the variables I'm pretty sure you'll find 1 that is null.
I have started doing asp.net mvc programming and like it more everyday.
Most of the examples I have seen use separate views for viewing and editing details of a specific entity.
E.g. - table of music albums linking to separate 'detail' and 'update' views
[Action] | Title | Artist
detail, update | Uuuh Baby | Barry White
detail, update | Mr Mojo | Barry White
With mvc how can I achieve a design where the R and the U (CRUD) are represented in a single view, and furthermore where the user can edit separate parts of the view, thus limiting the amount of data the user can edit before saving?
Example mockup - editing album detials:
I have achieved such a design with ajax calls, but Im curious how to do this without ajax.
Parts of my own take on this can be seen below. I use a flag (enum EditCode)
indicating which part of the view, if any, that has to render a form. Is such a design in accordance with the framework, could it be done more elegantly?
AlbumController
public class AlbumController : Controller
{
public ActionResult Index()
{
var albumDetails = from ManageVM in state.AlbumState.ToList()
select ManageVM.Value.Detail;
return View(albumDetails);
}
public ActionResult Manage(int albumId, EditCode editCode)
{
(state.AlbumState[albumId] as ManageVM).EditCode = (EditCode)editCode;
ViewData["albumId"] = albumId;
return View(state.AlbumState[albumId]);
}
[HttpGet]
public ActionResult Edit(int albumId, EditCode editCode)
{
return RedirectToAction("Manage", new { albumId = albumId, editCode = editCode });
}
// edit album details
[HttpPost]
public ActionResult EditDetail(int albumId, Detail details)
{
(state.AlbumState[albumId] as ManageVM).Detail = details;
return RedirectToAction("Manage", new { albumId = albumId, editCode = EditCode.NoEdit });// zero being standard
}
// edit album thought
[HttpPost]
public ActionResult EditThoughts(int albumId, List<Thought> thoughts)
{
(state.AlbumState[albumId] as ManageVM).Thoughts = thoughts;
return RedirectToAction("Manage", new { albumId = albumId, editCode = EditCode.NoEdit });// zero being standard
}
Flag - EditCode
public enum EditCode
{
NoEdit,
Details,
Genres,
Thoughts
}
Mangae view
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Controllers.ManageVM>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Manage
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Manage</h2>
<% if(Model.EditCode == MvcApplication1.Controllers.EditCode.Details)
{%>
<% Html.RenderPartial("_EditDetails", Model.Detail); %>
<% }else{%>
<% Html.RenderPartial("_ShowDetails", Model.Detail); %>
<% } %>
<hr />
<% if(Model.EditCode == MvcApplication1.Controllers.EditCode.Thoughts)
{%>
<% Html.RenderPartial("_EditThoughts", Model.Thoughts); %>
<% }else{%>
<% Html.RenderPartial("_ShowThoughts", Model.Thoughts); %>
<% } %>
The last part feels messy to me. I would recommend wrapping those with Html Helpers to clean up your view.
<h2>Manage</h2>
<% Html.RenderDetailsPartial(Model.EditCode) %>
<hr />
<% Html.RenderThoughtsPartial(Model.EditCode) %>
Let the HTMLHelper determine which view to use based on the EditCode.
In ASP.Net MVC I would like to render a different partial view depending on the renderview query string parameter.
Therefore providing the facility for the user to choose to view products by thumbnail or by details.
I have access to the chosen parameter in the controller but I do not know how to or, if I should be passing this to the view along with the products list so the view can implement the logic for deciding which partial view to display?
public ActionResult Products(string id, int? renderview)
{
var products = productRepository.GetProducts(id).ToList();
return View("Products", products);
}
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MLBWebRole.Models.Product>>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Products
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Products</h2>
<p>This is the Products page</p>
<p>thumbnails details</p>
<% if (renderview == 1)
{%>
<% Html.RenderPartial("ProductsDetailList"); %>
<% }
else
{ %>
<% Html.RenderPartial("ProductsThumbnailList"); %>
<% } %>
</asp:Content>
Your View Should be something like:
<%# Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Models.MyModel>" %>
Then in MyModel
Expose Property:
public bool RenderDetailView {get;set;}
In your controller action:
public ActionResult Products(string id, int? renderview)
{
var products = productRepository.GetProducts(id).ToList();
return View("Products", new MyModel {RenderDetailView = renderview.HasValue});
}
Then in your view, make check like:
<% if (Model.RenderDetailView)
Ideally, all the properties or parameters or data which a View needs in order to present itself should be part of Model.
I hope it helps.
An alternative approach would be to use Restful Urls to invoke the appropriate controller action and view.
This makes the urls reflect what you are seeing on the screen and makes the design more extensible; should you need to add other views of the data in the future (summary, latest, etc) you add the new view, no need for partials unless the main body of the view gets more complicated and has to be factored out to a partial view.
The URLs would look like:
~/product/1/detail
~/product/1/thumbnail
And correspond to ProductController methods:
public ActionResult Detail(String id)
{
var products = productRepository.GetProducts(id).ToList();
return View("Detail", products);
}
public ActionResult Thumbnail(string id)
{
var products = productRepository.GetProducts(id).ToList();
return View("Thumbnail", products);
}
You enable the routing with a route like:
{controller}/{id}/{action}
Paul's method is good, but if you decide you want to pass the int, you need to create a view model.
In your controller add this
public class ProductsFormViewModel
{
// Properties
public Products Products { get; private set; }
public int? Renderview { get; private set; }
// Constructor
public ProductsFormViewModel(Products p_products, int? p_renderView)
{
Products = p_products;
Renderview = renderView;
}
}
Then pass this into the view
return View(new ProductsFormViewModel(products, renderview);
And then in the view
Inherits="System.Web.Mvc.ViewPage<YourNamespace.Controllers.ProductsFormViewModel>"
I'd like to to provide data to a table in the views. The data is not only from database but also from a csv file.
Should I store the data in the ViewData, or should I store it in a object and pass it to views? What is the best approach, or any other methods I can use? Thx!
Use strongly-typed views and pass the object directly to the view:
// Model (PersonRepository class)
public static Person Get(Int32 id) {
using (MyContext context = new MyContext()) {
Person p = context.Person.First(p => Person.id == id);
return p;
}
}
...
// Controller
public ActionResult Show(Int32 id) {
return View(PersonsRepository.Get(id);
}
...
// View
<%# Page Inherits="System.Web.Mvc.ViewPage<Models.Person>" Title="" Language="C#" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
<%= Model.Id %> <br />
<%= Model.Name %> <br />
</asp:Content>
You should create a model object, fill it in the controller with data from heterogeneous sources and pass that model to the view.