Using Request.QueryString in ASP.NET Embedded Code Block - asp.net

I am attempting to pass a parameter from one file to another via the URL after a button is clicked. These are written with Express.js (index.ejs to items.ejs).
As it stands currently I am setting the URL parameter in a defined Javascript function:
function loadItems(page, subcategory) {
window.history.pushState(null, null, "?subcat=" + subcategory) //param set
$('#mainContent').load(page);
}
where subcategory is the changing variable.
From there I am trying to read this parameter during an ASP.NET function written in embedded code blocks.
<% if(items[i].subcategory === Request.QueryString["subcat"].Value) { %> //get param
<% if (items[i].status === "Supported") { %>
<tr class="success">
<td>Edit</td>
<td id="item name"><%= items[i].name%></td>
<td id="subcat name"><%= items[i].subcategory%></td>
<td id="item status"><%= items[i].status%></td>
<td id="item desc"><%= items[i].description%></td>
</tr>
However I am met with an error which states Request is not defined and a callback to the above if statement. It is my understanding that on the ASP.NET side of things, Request.QueryString is a part of System.Web.HttpContext.Current.
How would I go about including this into my code blocks so that I am able to pull the parameter from the URL? Or, if this is not the way to be looking at this problem, how should I go about it?

My advice would be to use code behind. Embedded code blocks are an old-school throwback from the asp days. But if you must, then you should be able to do something like this:
<%# Page Language="VB" %>
<script run=server>
Protected Function GetSubcat() As String
Return Request.QueryString["subcat"].Value
End Function
</script>
<form id="form1" runat="server">
Subcat value is <% =GetSubcat()%>.
</form>

Related

Create form action as variable

I have t following ASPX source :
<form name="AddComment" action="ViewArticle.aspx?ArticleID=<%=ArticleID %>" method="post" runat="server">
The problem is that when I click submit I got this url
http://localhost:61175/WebSite1/ViewArticle.aspx?ArticleID=%3C%=ArticleID%20%%3E
But I want get this URL :
http://localhost:61175/WebSite1/ViewArticle.aspx?ArticleID=1
If I delete the "runat="server"" command it works fine, but can this form work with the
variable and the runat server at the same time?
Maybe you can try setting the action just before the form markup like this (or in codebehind, at your choice)
<%
this.Form.Action = "ViewArticle.aspx?ArticleID=" + ArticleID.ToString();
%>
<form name="AddComment" method="post" runat="server">
In server side controls you can't do such things as <%= ActionID %> you can only bind <%# ActionID %>.
The upper solution won't work, becouse the form is not that form. You have to give a control ID + name than setup the post url. If it's not an option you can dinamicly search for form item in the control tree, so dynamic ID-s can be handled.

asp.net code displays code itself instead of output in browser

The following code displays as it is in browser instead of expected output. I have the table in sql server 2008. I have this code in webmatrix.
<%# Page Language="VB" %>
#{
var db = Database.Open("databasename"); 'database name in sql server is 'databasename'
var selectQueryString = "SELECT column_date, sum(qty1) as quantity1,
sum(qty2) as quantity2, sum(qty3) as quantity3
from tbldaily group by column_date order by column_date";
}
<!DOCTYPE html>
<html>
<body>
<h1>First table test</h1>
<table>
<tr>
<th>at_date</th>
<th>quantity1</th>
<th>quantity2</th>
<th>quantity3</th>
</tr>
#foreach(var row in db.Query(selectQueryString))
{
<tr>
<td>#row.column_date</td>
<td>#row.quantity1</td>
<td>#row.quantity2</td>
<td>#row.quantity3</td>
</tr>
}
</table>
</body>
</html>
I feel there is mistake somewhere in this code. Can you help me to fix this? Please let me know if you want more information regarding my database structure or table that may help to understand my scenario better
Looks like you are mixing Razor syntax with WebPages. Name your file *.cshtml and remove the first line which is for WebPages. The rest of your code is valid C# razor.
I think he needs the opposite of that. Keep it .aspx.
So wherever you have # tags to mark the asp code, use aspx escapes instead
<% For i As Integer = 0 To .... %>
<tr> <td> <%= row.column_date %> </td> ......
<% Next%>

custom controls and query string(asp.net)

How to call a custom control when query string is changed?
My example not work?Why?
<% if(Convert.ToInt32(Request.QueryString["id"])==6){ %>
<answer:answer_n id="give_me_top_five_news" runat="server" />
<%} %>
<% if(Request.QueryString["do"]=="registracija"){
Page.Header.Title = "HHHHH";
%>
<reg:f_reg id="custom_controls_for_registration" runat="server" />
<%} %>
Changed in what fashion? Anytime you load the page with a new URL and query string, the page will be loaded for the first time. You would have to save the info you wanted to store in the Session (for example) and then in the Page_Load event check the query string vs the Session variable to see if they are the same or different.
There may be different ways to do it, but that's what comes to mind off the cuff.

Why can't I use an iteration variable in a LoginView?

I am building a .NET MVC app that has a page with a list of delete buttons, one for each item in a list. The problem I'm having is that the foreach variable "item" is not visible inside the LoginView, which results in the following error:
Compiler Error Message: CS0103: The name 'item' does not exist in the current context
Below is a simplified version of the view. The error occurs at the "new {id=item.Id}" in the LoggedInTemplate - the reference to "item" in the ActionLink works fine:
<% foreach (var item in Model) { %>
<%= Html.ActionLink("Item", "Details", new { id = item.Id })%>
<asp:LoginView runat="server">
<LoggedInTemplate>
<% using( Html.BeginForm( "Delete", "Items", new {id=item.Id}, FormMethod.Post))
{ %>
<input type="submit" value="Delete" runat="server" />
<% } %>
</LoggedInTemplate>
</asp:LoginView>
<% } %>
To clarify the problem is not that the Model has not been successfully passed to the View. The Model is visible from both inside and outside the LoginView. The foreach loop as no problem in iterating through the items in the Model (which is a List). The problem is that the iteration variable "item" is not accessible from within the LoginView - though the original Model is.
Is there any way to pass "item" through to the LoginView's templates? Or is building LoginViews within a foreach loops the wrong way of doing things?
Is there a scoping rule that prevents using local variables within controls - perhaps because the control is rendered at a different time to the main page?
With ASP.NET MVC you really shouldn't use user/custom controls, so if you omit the <asp:LoginView/> and write a line of code to check if the user is authenticated, you are good to go.
Instead of your current code:
<asp:LoginView runat="server">
<LoggedInTemplate>
<div>Show this to authenticated users only</div>
</LoggedInTemplate>
</asp:LoginView>
Just use an if-statement and the value of Request.IsAuthenticated:
<% if (Request.IsAuthenticated) { %>
<div>Show this to authenticated users only</div>
<% } %>
Are you passing the Model to the view and are you also inheriting from the model within that view?
So if this is a View then in your C# code you need to return the list of items like return View(listofitems);
If this is a partial view then <% Html.RenderPartial("MyPartial", listofitems) %>
And in the view you need to
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IQueryable<ListOfItems>>" %>
If all that is in place then it should work no probs.
<% foreach (var item in Model) { %>
<%= Html.ActionLink("Item", "Details", new { id = item.Id })%>
<%= if( Request.IsAuthenticated ) {
using( Html.BeginForm( "Delete", "Items", new {id=item.Id}, FormMethod.Post))
{ %>
<input type="submit" value="Delete" runat="server" />
}
} %>
<% } %>
There is no need to use the LoginView, its not really giving you anything. Use something like the above instead.
Alternatively, you can move the decision of whether to show the delete option for the specific item into the controller, so instead of doing if( Request.IsAuthenticated ) you would do if( item.ShowDelete ) ... assuming item's type is a view model. Another option is to use an extension method for the same, item.ShowDelete(). I prefer the earlier, because there might be logic associated to deciding whether to show delete for a given item, so its better to not have it in the controller or a related logic.

Issue with asp:ContentPlaceHolder and code blocks

When a content placeholder contains any code blocks it reports that the control collection is empty.
For instance:
MasterPage.aspx
<asp:ContentPlaceHolder ID="Content1" runat="server" />
<asp:ContentPlaceHolder ID="Content2" runat="server" />
<div>Content1: <%= Content1.Controls.Count %></div>
<div>Content2: <%= Content2.Controls.Count %></div>
APage.aspx
<asp:Content ContentPlaceHolderID="Content1" runat="server">
Plain text content.
</asp:Content>
<asp:Content ContentPlaceHolderID="Content2" runat="server">
<%= "Code block content." %>
</asp:Content>
This will render the following:
Plain text content. Code block content.
Content1: 1
Content2: 0
Why is the master page's ContentPlaceHolder.Controls collection empty?
I want to check whether the ContentPlaceHolder has been populated (see also this question) but can't if it contains any <%= blocks.
Does anyone know a way around this?
As promised, I said I would take a look. Sorry I never uploaded last night, long day and needed to hit the hay!
So, I was checking out the ContentPlaceHolder.Controls collection differences between how they are populated. I noticed that when the code block is used, it flips to read only. At any other point, it will simply be empty or populated.
I therefore decided to throw in an extension method to check it for us:
ContentPlaceHolderExtensions.cs
public static class ContentPlaceHolderExtensions
{
public static bool ContainsControlsOrCodeBlock(this ContentPlaceHolder placeHolder)
{
if (placeHolder.Controls.Count > 0)
return true;
return placeHolder.Controls.IsReadOnly;
}
}
And then check this in the master page:
Site.Master
<asp:ContentPlaceHolder ID="Content1" runat="server" />
<asp:ContentPlaceHolder ID="Content2" runat="server" />
<asp:ContentPlaceHolder ID="Content3" runat="server" />
<div>Content1: <%= Content1.Controls.Count %></div>
<div>Content2: <%= Content2.Controls.Count %></div>
<div>Content3: <%= Content3.Controls.Count %></div>
<div>Content1 (Ex. Meth.): <%= Content1.ContainsControlsOrCodeBlock() %></div>
<div>Content2 (Ex. Meth.): <%= Content2.ContainsControlsOrCodeBlock() %></div>
<div>Content3 (Ex. Meth.): <%= Content3.ContainsControlsOrCodeBlock() %></div>
As proof-of-concept, I then added a content page:
Index.aspx
<asp:Content ContentPlaceHolderID="Content1" runat="server">
Plain Text Content
</asp:Content>
<asp:Content ContentPlaceHolderID="Content2" runat="server">
<%= "Code block content" %>
</asp:Content>
And all rendered as expected (I believe)..
TBH, while it is not perfect.. I don't think we can get much more elegance in this situation. I am not sure how other control collections are set up in these different scenarios, so I only bolted on to the ContentPlaceHolder control.. Other templated controls may or may not work the same.
Thoughts?
You can download the project from here:
http://code.google.com/p/robcthegeek/source/browse/#svn/trunk/stackoverflow/964724
Too much for a comment, here's the full code that I finally got working (adapted from #Rob Cooper's answer):
public static bool HasContent( this ContentPlaceHolder placeHolder )
{
if ( placeHolder.Controls.Count > 0 )
{
LiteralControl textBlock;
ContentPlaceHolder subContent;
foreach ( var ctrl in placeHolder.Controls )
if ( (textBlock = ctrl as LiteralControl) != null )
{ //lit ctrls will hold any blocks of text
if ( textBlock.Text != null && textBlock.Text.Trim() != "" )
return true;
}
else if ( (subContent = ctrl as ContentPlaceHolder) != null )
{ //sub content controls should call this recursively
if ( subContent.HasContent() )
return true;
}
else return true; //any other control counts as content
//controls found, but all are empty
return false;
}
//if any code blocks are used the render mode will be different and no controls will
//be in the collection, however it will be read only
return placeHolder.Controls.IsReadOnly;
}
This includes two extra checks - firstly for empty literal controls (which occur if the page includes the <asp:Content tags with any whitespace between them) and then for sub-ContentPlaceHolder which will occur for any nested master pages.
The controls collection is empty because when <%= %> script tags are present, literal controls are not added to the control tree. However, server controls will still get added. So:
<asp:Content ID="Content2" ContentPlaceHolderID="Content2" Runat="Server">
<%= "Code block content." %>
<asp:GridView runat="server" ID="gvTest" />
</asp:Content>
<div>Content2: <%= Content2.Controls.Count %></div>
will return
Content 2: 1
Rick Strahl has a great article that explains this behavior:
To make code like this work, ASP.NET
needs to override the rendering of the
particular container in which any
script code is hosted. It does this by
using SetRenderMethodDelegate on the
container and creating a custom
rendering method ...
Rather than building up the control
tree literal controls, ASP.NET only
adds server controls to the control
tree when <% %> tags are present for a
container. To handle the literal
content and the script markup, ASP.NET
generates a custom rendering method.
This method then explicitly writes out
any static HTML content and any script
expressions using an HTML TextWriter.
Any script code (<% %>) is generated
as raw code of the method itself.
Unfortunately I can't think of any elegant solution to this conundrum.

Resources