I have been trying to organise my views to optimize load times by having css in the head and scripts at the end of the body.
To this end I have created masterpages that have 3 content placeholders: styles, maincontent and scripts.
With the (achieved) aim that when I render a single view with a master this neatly can collate all the shared components and specific page components into their respective places in the rendered page. The difficultly comes when I try rendering a master-detail model.
Consider the following:
I have a Master-Detail model say Order-OrderItems and views for the Order and views for the OrderItems. In an effort to be DRY and not to repeat myself (doh! I just did right then :) ) I would like to partially render the OrderItems list view in the Order header view and still achieve the correct element layout i.e: have the any specific css be rendered into the content placeholder in the head, content into the main content placeholder and scripts into my scripts content placeholder at the bottom of the body.
I have a nasty hack at the moment but wondered if there is a cleaner way of doing this.
My current hack is the equivalent of a sql cross join with a where clause in that I do a partial render of the orderitems view in each contentplaceholder of the order view and inject the name of that placeholder into the viewdata. In the orderitems view if the placeholder name does not equal the target placeholder, I return and there by only the css get rendered into the css place holder etc. To re-phrase it, I render the child three times in the parent, while in the child I return a different part of the content for each rendering.
Smells funny and not very elegant as the child has to know that it is being rendered etc.
My next thought is to try intercepting a copy of the ViewPage and taking control of the rendering using using SetRenderMethodDelegate by only calling render on the target contentplaceholder control but this is getting very tangled at this point.
Can anyone suggest a better way that maintains code re-use and optimal html output?
Some example code:
<%# Master Language="C#" ... %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Master-Detail</title>
<!--common styles-->
<link type="text/css" href="my.css" rel="stylesheet" />
<asp:ContentPlaceHolder ID="Styles" runat="server" ></asp:ContentPlaceHolder>
</head>
<body>
<!--common markup-->
<h2>Master Markup</h2>
<asp:ContentPlaceHolder ID="mainContent" runat="server"></asp:ContentPlaceHolder>
<!--common scripts-->
<script type="text/javascript" src="/scripts/my.js"></script>
<asp:ContentPlaceHolder ID="Scripts" runat="server"></asp:ContentPlaceHolder>
</body>
</html>
Order View
<%# Page Title="Order" Language="C#" MasterPageFile="~/Views/Shared/my.Master" ... %>
<asp:Content ContentPlaceHolderID="Styles" runat="server">
<style type="text/css">
/*order styles*/
</style>
<%
var partialContext = this.Html.GetViewContext("OrderDetails", "List", this.ViewData.Model.Items, this.ViewData);
partialContext.RenderContentPlaceHolder("Styles");
%>
</asp:Content>
<asp:Content ContentPlaceHolderID="MainContent" runat="server">
<h3>Order Markup</h3>
<%
var partialContext = this.Html.GetViewContext("OrderDetails", "List", this.ViewData.Model.Items, this.ViewData);
partialContext.RenderContentPlaceHolder("MainContent");
%>
</asp:Content>
<asp:Content ContentPlaceHolderID="Scripts" runat="server">
<script type="text/javascript">
/*order specific script*/
</script>
<%
var partialContext = this.Html.GetViewContext("OrderDetails", "List", this.ViewData.Model.Items, this.ViewData);
partialContext.RenderContentPlaceHolder("Scripts");
%>
</asp:Content>
Order Items View:
<%# Page Title="OrderItems" Language="C#" MasterPageFile="my.aspx" ... %>
<asp:Content ID="Content2" ContentPlaceHolderID="Styles" runat="server">
<% if (ViewData["placeHolderName"] != null && ViewData["placeHolderName"].ToString().ToLower() != "styles")
return; %>
<style type="text/css">
/*OrderItems style*/
</style>
</asp:Content>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<% if (ViewData["placeHolderName"] != null && ViewData["placeHolderName"].ToString().ToLower() != "maincontent")
return; %>
<h4>Order Items MarkUp</h4>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="Scripts" runat="server">
<% if (ViewData["placeHolderName"] != null && ViewData["placeHolderName"].ToString().ToLower() != "scripts")
return; %>
<script type="text/javascript">
/*Order Items script*/
</script>
</asp:Content>
Where there are a couple of extension methods:
public static ViewContext GetViewContext(this HtmlHelper htmlHelper, String controller, String viewName, Object model, ViewDataDictionary viewData)
{
var routeData = new System.Web.Routing.RouteData();
routeData.Values["controller"] = controller;
var controllerContext = new ControllerContext(htmlHelper.ViewContext.HttpContext, routeData, htmlHelper.ViewContext.Controller);
var viewEngineResult = ViewEngines.Engines.FindView(controllerContext, viewName, "Partial");
var viewData2 = new ViewDataDictionary(viewData);
viewData2.Model = model;
var viewContext = new ViewContext(controllerContext, viewEngineResult.View, viewData2, htmlHelper.ViewContext.TempData, htmlHelper.ViewContext.Writer);
return viewContext;
}
public static void RenderContentPlaceHolder(this ViewContext context, String placeHolderName)
{
context.ViewData["placeHolderName"] = placeHolderName;
context.View.Render(context, context.Writer);
context.ViewData.Remove("placeHolderName");
}
Have a look at this similar question asked some time ago:
How can I include css files from an MVC partial control?
Especially the link provided in the accepted answer is quite interesting:
http://www.codeproject.com/Articles/38542/Include-Stylesheets-and-Scripts-From-A-WebControl-.aspx
edit: You can find another blogpost of the same author updated for MVC 2 here: http://somewebguy.wordpress.com/2010/04/06/adding-stylesheets-scripts-in-asp-net-mvc2/
Related
Can you help on this
I have two Partial Views in the page, the First Partial View have (Input Text and Submit Button )
Whenever the user Press Submit Button (from PartialView1 ) , I would like to ready the input Text from PartialView2
can you please help on How I can Read the Partial View1's Input Text from PartialView2 when Pressing the PartialView1's submit button ?
More specifically :reading that value from the "Action" that is rendering the PartialView2
more Details:
It is something like that : read the values from all textboxes in partialview1 and assign the all content into textbox2 in partial2 when press submit button from PartialView1
below is an example
this is my main View index.aspx:
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<!DOCTYPE html>
<html>
<head runat="server">
<title>Index</title>
</head>
<body>
<div>
<%Html.RenderAction("ActionSenderForPartial1", "Controllername"); %>
</div>
<h2>Result</h2>
<div>
<%Html.RenderAction("ActionReceiverForpartial2", "Controllername"); %>
</div>
</body>
</html>
the PartialView 1 "Partial1"
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<MvcApplication3.Models.UIField>>" %>
<form method="post">
<%:Html.TextBox("TextBox1") %>
<%:Html.TextBox("TextBox2") %>
.
.
<%:Html.TextBox("TextBoxN") %>
<p>
<button name="btnaction" value="search">Search</button>
<button name="btnaction" value="cancel">Cancel</button>
</p>
</form>
for PartialView2: "Partial2.ascx"
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>
<%:Html.TextBox("TextBox2") %>
The actions "" & "" :
[ChildActionOnly]
public ActionResult ActionSenderForPartial1()
{
return PartialView();
}
[ChildActionOnly]
public ActionResult ActionReceiverForpartial2(string btnaction)
{
string _searchQuery = string.Empty;
--How to read the all TextBoxes contents from PartialView1 and assign the concatenated values to the TextBox2 at this partialview2
return PartialView();
}
In case there is many options I would highly appreciate to mention advising the best one as I am new in MVC.
Thanks so much
if any actual example will be highly appreciated
Please Note: i Have an idea on how to do it by Ajax but I would to do it without using Ajax .
Many Thanks
Nahed
I am trying to export gridview to excel / pdf / word format
I have added all necessary implementation but still it gives me an error like "control of type 'gridview' must be placed inside a form tag with runat=server"
Please look at my code below ,
.aspx page
<%# Page Title="" Language="C#" MasterPageFile="~/MasterPages/OrganizationMaster.Master" EnableEventValidation="false" AutoEventWireup="true" CodeBehind="SearchInvoice.aspx.cs" Inherits="Site.pages.ContactStaff.ViewInvoice" %>
.aspx.cs page
public override void VerifyRenderingInServerForm(Control control)
{
/* Confirms that an HtmlForm control is rendered for the specified ASP.NET
server control at run time. */
}
.ascx.cs control
protected void btnExport_Click(object sender, EventArgs e)
{
if (ddlExport.SelectedIndex != 0)
{
if (ddlExport.SelectedValue == "Word")
{
Response.AddHeader("content-disposition", "attachment;filename=OtherCourses.doc");
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.ContentType = "application/vnd.word";
StringWriter stringWrite = new StringWriter();
HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);
List<InvoiceHelper> invoicelist = svc.RetriveInvoiceList(Request.Url);
grdinvoicelist.AllowPaging = false;
grdinvoicelist.DataSource = invoicelist;
grdinvoicelist.DataBind();
grdinvoicelist.RenderControl(htmlWrite);
Response.Write(stringWrite.ToString());
Response.End();
}
}
}
You might have same problem as I had.
Inside your MasterPage you already have a form tag,
When you do 2nd form tag in your webform.
try using cleanest masterpage as possible such as:
<%# Master Language="C#" AutoEventWireup="true" CodeBehind="TotalEmpty.master.cs"
Inherits="ProjectName.MasterPages.TotalEmpty" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<div>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</body>
</html>
I want to double click on a cell of a gridpanel an call another
action/view with extra parameter example:
The gridpanel is in .../Student and I want to show the details of one
student in another page ex: /Student/Detail/1 double clicking on his
name, id, or wherever data is on his record.
Sorry for the bad english
I tried this
#(
Html.X().GridPanel()
.Title("Students")
.Width(550)
.Height(200)
.ForceFit(true)
.Store(Html.X().Store().Model(Html.X().Model()
.Fields(fields =>
{
fields.Add(Html.X().ModelField().Name("StudentID"));
fields.Add(Html.X().ModelField().Name("LastName"));
fields.Add(Html.X().ModelField().Name("FirstMidName"));
fields.Add(Html.X().ModelField().Name("EnrollmentDate"));
}
)
).DataSource(Model)
).ColumnModel(
Html.X().Column().Text("Student ID").DataIndex("StudentID"),
Html.X().Column().Text("Last Name").DataIndex("LastName"),
Html.X().Column().Text("First Name").DataIndex("FirstMidName"),
Html.X().DateColumn().Text("Enrollment").DataIndex("EnrollmentDate")
).DirectEvents(de =>
{
de.CellDblClick.Url = "Edit"; // also tried
de.CellDblClick.Action = "Edit";
de.CellDblClick.ExtraParams.Add(1); //static
later I'll add the StudentID here
}
)
)
The gridpanel show the data without problem but when I doubleclick on a
cell this is the request that it's sended
localhost:10782/Student/Edit?_dc=1359052548829
instead of this
localhost:10782/Student/Edit/1
I can suggest to manage an URL with a Before handler.
To remove "?dc..." from an URL, please set up DisableCaching="false".
<%# Page Language="C#" %>
<%# Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
<!DOCTYPE html>
<html>
<head runat="server">
<title>Ext.NET v2 Example</title>
<script>
var counter = 1;
</script>
</head>
<body>
<ext:ResourceManager runat="server" />
<ext:Button runat="server" Text="Test">
<DirectEvents>
<Click Url="Some URL" Before="o.url = o.rawUrl + counter++;" DisableCaching="false">
<CustomConfig>
<ext:ConfigItem Name="rawUrl" Value="Controller/Action/" Mode="Value" />
</CustomConfig>
</Click>
</DirectEvents>
</ext:Button>
</body>
</html>
So, I'm getting a 404 error on my current MVC project on submit. I'm new to MVC, so I'm likely doing something exceptionally stupid. Here's the relevant code...
<%# Page Title="Pies" Language="C#" Inherits="System.Web.Mvc.ViewPage" MasterPageFile="~/site.master" %>
<asp:Content ContentPlaceHolderID="MainContent" runat="server">
<h1>Oh Boy Pies</h1>
<p>Tell us about the pies!</p>
<form action="Process" method="post">
<div class="inputdiv">
<span class="spaced">Name:</span>
<%= Html.TextBox("name") %>
<%= Html.ValidationMessage("name", "*") %>
</div>
</form>
And the relevant handler is...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
namespace tabdemo.Controllers
{
public class HomeController : Controller
{
public ActionResult Index ()
{
ViewData ["Message"] = "Demo!";
return View ();
}
public ActionResult Process (FormCollection form)
{
Response.Write (form ["name"]);
Response.End ();
return Redirect ("Index.aspx");
}
}
}
Also, can people explain how this would be implemented using TextBoxFor, for example? I've seen examples of it, but I don't understand it at all.
edit: Here's the masterpage
<%# Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<asp:ContentPlaceHolder ID="MainContent" runat="server">
</asp:ContentPlaceHolder>
</body>
</html>
it should be return RedirectToAction("Index"). MVC does not use PAGES, instead relies on Controller to route the request.
Controllers return the View, or Redirect to another Controller, which renders the view.
EDIT
And yes, the action method was incorrect(just saw)
<form action="/Home/Process" method="post">
<div class="inputdiv">
<span class="spaced">Name:</span>
<%= Html.TextBox("name") %>
<%= Html.ValidationMessage("name", "*") %>
</div>
</form>
Hello Guys i am having following code in my Content page of my master page
<%# Page Title="About Us" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeFile="Description.aspx.cs" Inherits="Description" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
<script src="http://maps.google.com/maps?file=api&v=2&key=key&sensor=true"
type="text/javascript"></script>
<script type="text/javascript">
function initialize()
{
if (GBrowserIsCompatible())
{
var map = new GMap2(document.getElementById("map_canvas"));
map.setCenter(new GLatLng(20,30), 10);// I want to change these coordinates
map.setUIToDefault();
}
}
$(document).ready(function ()
{
initialize();
});
</script>
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<div id="main">
</div>
</asp:content>
In above code i want to fetch coordinates from code behind .
I am having coordinates in code behind ex string coor = "20,30";
so inside page load event how can i put the value of this variable in java script code.
Should I create a String literal there ? or something else.
You could store them in a property and then use them:
map.setCenter(new GLatLng(<%= Lat %>, <%= Lon %>), 10);
where Lat and Lon are two public integer properties in your code behind. You could also use methods if you will.