Is there an easy way to comment out a loop which renders some html and has inline html without deleting anything? I am copying and pasting some code from another project to rebuild a new public front end from a working internal backend.
Below is an example of a sitation in which it would be nice...in asp.net MVC 2
<%
List<VehicleBodyTypeListItem> lstBodyTypes = (List<VehicleBodyTypeListItem>)ViewData["ddBodyType"];
foreach (VehicleBodyTypeListItem bodyType in lstBodyTypes)
{
%>
<a href="<%= Url.Action( "Search", new { BodyTypeID=bodyType.BodyTypeID, BodyType= Url.Encode( Html.WebLinkify( bodyType.BodyType))}) + (string)ViewData["httpCriteria"] %>">
<%= Html.Encode( String.Format( "{0} ({1})", bodyType.BodyType, bodyType.Count.ToString())) %> </a>
<br />
<%
}
%>
I have not completed the method that populates this list yet, and have about 5 more like it further down the page.
The keyboard shortcut is, if you select the section you want commented out is: CTRL + K + C will comment out code. CTRL + K + U will uncomment the code.
Comment a block of code by enclosing it in #* and *#
Do you mean adding comments to the code. If so you just need to add //. Like here:
<%
List<VehicleBodyTypeListItem> lstBodyTypes = (List<VehicleBodyTypeListItem>)ViewData["ddBodyType"];
foreach (VehicleBodyTypeListItem bodyType in lstBodyTypes) // Here there's a comment
{
%>
<a href="<%= Url.Action( "Search", new { BodyTypeID=bodyType.BodyTypeID, BodyType= Url.Encode( Html.WebLinkify( bodyType.BodyType))}) + (string)ViewData["httpCriteria"] %>">
<%= Html.Encode( String.Format( "{0} ({1})", bodyType.BodyType, bodyType.Count.ToString())) %> </a>
<br />
<%
}
%>
Related
Hi I'm using silverstripe 2.4.7 and I'm having difficulty getting the pagination to work. I've created a function in my page.php to get the latest articles like so
function AllNewsPosts($num=1) {
$news = DataObject::get_one("NewsHolder");
return ($news) ? DataObject::get("NewsEntry", "ParentID > 0", "Date DESC", "", $num) : false;
}
Then when i put this function into the control and pagination tags one article shows up however the links to the concurrent articles do not work - essentially the pagination is not working and I'm not sure how to fix it
<% if AllNewsPosts %>
<% control AllNewsPosts %>
<div class="event">
<h2>$MenuTitle |<span class="date"> $Date.Time $Date.Long</span></h2>
<p>$Content.FirstParagraph</p>
See more about this event
</div>
<% end_control %>
<% else %>
<div class="no-entry">'There are no entries'</div>
<% end_if %>
<% if AllNewsPosts.MoreThanOnePage %>
<div id="PageNumbers">
<p>
<% if AllNewsPosts.NotFirstPage %>
<a class="prev" href="$AllNewsPosts.PrevLink" title="View the previous page"><span class="yellow-background">Prev</span></a>
<% end_if %>
<span>
<% control AllNewsPosts.PaginationSummary(0) %>
<% if CurrentBool %>
<span class="current">$PageNum</span>
<% else %>
<% if Link %>
$PageNum
<% else %>
…
<% end_if %>
<% end_if %>
<% end_control %>
</span>
<% if AllNewsPosts.NotLastPage %>
<a class="next" href="$AllNewsPosts.NextLink" title="View the next page"><span class="yellow-background">Next</span></a>
<% end_if %>
</p>
</div>
<% end_if %>
Any help is much appreciated
Note: The following answer is for Silverstripe 2.4. This should not be used for Silverstripe 3.0+ sites. From 3.0 and onwards the PaginatedList object makes pagination much easier.
You are not setting a limit on how many entries to retrieve in your query, or where to start from.
The following tutorial explains how to apply pagination to a set of data objects exactly as you are trying to do:
http://www.ssbits.com/tutorials/2010/paginating-a-filtered-dataobjectset/
Here is an attempt at altering your function to include limit and start as needed for pagination:
PHP
function AllNewsPosts() {
if(!isset($_GET['start']) || !is_numeric($_GET['start']) || (int)$_GET['start'] < 1)
{
$_GET['start'] = 0;
}
$SQL_start = (int)$_GET['start'];
$newsEntries = DataObject::get('NewsEntry', '', 'Date DESC');
$doSet = new DataObjectSet();
foreach ($newsEntries as $newsEntry) {
if ($newsEntry->canView()) {
$doSet->push($newsEntry);
}
}
$doSet->setPageLimits($SQL_start, 10, $doSet->Count());
return $doSet;
}
Note the above will display 10 items per page. You can change this to however you need per page.
Currently I have 4 spans with alternating CSS tags.
<% var index =0 ; %>
<% foreach (var item in Model.Take(4)) {
var css = (index%2==0)?"even":"odd";
%>
<span class="featured-products <%= css %>">
<%= Html.Photo(PhotoExtensions.PhotoSizeType.HomepageThumb, item.DefaultPhoto)%>
<%= item.ProductName%>
</span>
<%
index ++ ;
} %>
But I need for the last span to contain an extra CSS tag "last". Ive tried a couple of different methods but they all failed. Any help? Thanks.
Have you tried using the :last-child CSS selector? It may not be necessary to add additional markup if you can achieve what you want through CSS.
If you don't want to use CSS.
<% var index = 0; %>
<% var items = Model.Take(4); %>
<% foreach (var item in items) {
var css = (index%2==0)?"":"odd";
if(index == items.Count - 1)
{
css = " last";
}
%>
<span class="featured-products <%= css %>">
<%= Html.Photo(PhotoExtensions.PhotoSizeType.HomepageThumb, item.DefaultPhoto)%>
<%= item.ProductName%>
</span>
<%
index ++ ;
} %>
Also, I would recommend cleaning this code up. You don't need to put <% and %> everywhere.
Update: A bit cleaner way of writing what you're doing. Definately not the cleanest but a good start.
<%
var index = 0;
var items = Model.Take(4);
foreach (var item in items) {
var css = (index%2==0)?"":"odd";
if(index == items.Count - 1)
{
css = " last";
}
%>
<span class="featured-products <%= css %>">
<%= Html.Photo(PhotoExtensions.PhotoSizeType.HomepageThumb, item.DefaultPhoto)%>
<%= item.ProductName%>
</span>
<%
index ++ ;
}
%>
I am staring at the worst mess, my monitor isn't tall enough to see what is going on, and VS 2010 is no help at all.
I do not have any idea how to refactor this trash.
It's 11 AM and I feel like pouring a drink already.
Is this just the final proof that I have no business coding? Be honest.
<div id="followedFriends">
<% if (Model.FollowedFriends.Count() > 0)
{
foreach (var friend in Model.FollowedFriends)
{ %>
<div id="friendContainer">
<div class="followedFriend">
<div class="userName">
<%= Html.ActionLink(friend.FoFriend.UserName, "Visitor", "Home", new {userID = friend.FoFriend.UserId}, null)%></div>
Currently reading:
<br />
<div class="bookLinks">
<% if (friend.BookCount != 0)
{ %>
<% if (friend.BookCount <= 5)
{ %>
<%= friend.BookLinks%>
<%}
else
{ %>
<%:Html.ActionLink(friend.BookCount + " different books.", "Visitor", "Home", new {userID = friend.FoFriend.UserId}, null)%>
<%}
}
else
{ %>
Nothing, it appears...
<%}%>
</div>
<%if (friend.ReviewCount != 0)
{%>
New review for:
<div class="reviewLinks">
<%if (friend.ReviewCount <= 5)
{ %>
<%= friend.ReviewLinks%>
<%}
else
{%>
<%: friend.ReviewCount %>
different books
<%}%></div>
<%}
if (friend.QuoteCount != 0)
{%>
<span class="highlight">▸</span>
<%: friend.QuoteCount%>
new
<%if (friend.QuoteCount != 1)
{ %>quotes
<%}
else
{ %>
quote
<%} %>
<%}%>
</div>
</div>
<%}
}%>
</div>
<%} %>
Update
Since someone was asking, here is the pertinent portion of the View Model:
public class FollowedFriend
{
public aspnet_User FoFriend { get; set; }
public string BookLinks { get; set; }
public int BookCount { get; set; }
public string ReviewLinks { get; set; }
public int ReviewCount { get; set; }
public int QuoteCount { get; set; }
public FollowedFriend(Guid userID, DateTime lastVisit)
{
using (var context = new BookNotesEntities())
{
FoFriend = context.aspnet_Users.SingleOrDefault(u => u.UserId == userID);
var reading = context.Books.Where(b => b.UserID == userID && b.CurrentlyReading == true).ToList();
BookCount = reading.Count;
if (BookCount <= 5)
BookLinks = Book.ConvertBooksToLinks("Book/Details", reading);
else
BookLinks = "";
var recentBooks = context.Books.Where(b => b.UserID == userID
&& b.Review.DateCreated >= lastVisit).OrderByDescending(b => b.DateCreated).ToList();
if (recentBooks.Count <= 5)
ReviewLinks = Book.ConvertBooksToLinks("/Book/Details", recentBooks);
else
ReviewLinks = "";
ReviewCount = recentBooks.Count;
QuoteCount = context.Quotes.Count(q => q.UserID == userID && q.DateCreated >= lastVisit);
}
}
}
Let's start with a maxim that was initially proposed by Rob Conery: if there's an embedded "if" somewhere in your View, it's probably an indicator that you should either A.) create an HtmlHelper or B.) retract the logic from the view and insert it into your ViewModel.
By doing so, you can clean up your View to look something like this (you get the idea):
<div id="followedFriends">
<% foreach (var friend in Model.FollowedFriends) { %>
<div id="friendContainer">
<div class="followedFriend">
<div class="userName">
<%: Html.ActionLink(friend.FoFriend.UserName, "Visitor", "Home", new {userID = friend.FoFriend.UserId}, null)%>
</div>
Currently reading:
<br />
<div class="bookLinks">
<%: Html.DisplayBooklinks(friend) %>
</div>
<div class="bookReviews">
<%: Html.DisplayBookReviews(friend) %>
</div>
<div class="bookQuotes">
<%: Html.DisplayQuotes(friend) %>
</div>
</div>
</div>
<% } %>
</div>
At this point, if there's any chance that this piece of UI might be consumed in some other page, you should consider throwing it into a user control. By doing so, your view could now look something like this:
<% Html.RenderPartial("FriendDetails", Model.FollowedFriends); %>
Ultimately, whenever your View starts to look like soup, it's because your view is doing too much thinking. Which, in turn, means: some other layer of your application isn't thinking enough. By pinpointing logic in your Views, and by determining what abstractions might aid you in your attempt to remain DRY, your Views will become much more readable and much more maintainable.
I would factor some of that inline logic to an HtmlHelperExtension method and then create a DisplayTemplate "Friend"
<div id="followedFriends">
<% if (Model.FollowedFriends.Any()) {
foreach (var friend in Model.FollowedFriends) {
<%=Html.DisplayFor(friend) %>
<% } %>
<% } %>
</div>
And your DisplayTemplate "Friend" would look something like this:
<div id="friendContainer">
<div class="followedFriend">
<div class="userName">
<%= Html.ActionLink(friend.FoFriend.UserName, "Visitor", "Home", new {userID = friend.FoFriend.UserId}, null)%></div>
Currently reading:
<br />
<%=Html.BookInformation(friend) %>
<%=Html.BookReview(friend) %>
<%=Html.Quotes(friend) %>
</div>
</div>
</div>
Rather than making HtmlHelperExtensions you could just create more DisplayTemplates and specifically call them: DisplayFor("BookReview", friend)
Let me start by saying, we've all been there...
For your particular problem, I'd consider a few of the following "tools":
Partial Views: when you have a lot of nested <div> tags, for instance, you may want to consider creating some partial views where appropriate.
Use the Controller for Business Logic: Some of your logic should be done in the controller, where it's easier to break things up and call different helper methods to apply the logic. Consider passing to your view a custom object (a ViewModel if you will) that has all the business logic parsed. For example, things like displaying "quote" vs "quotes" could be done in a ViewModel object's "DisplayValue"-type property.
HTML Helpers: These little extensions can help take care of extracting the many if/else statements that you have into an easily readable method - and they could be re-used on other pages if written generally enough.
Lastly, I'd say, go get some fresh air and come back with only one thing in mind: simplify! Often we get caught up with a long list of tasks that need to be done and we get lost in our own soup or spaghetti or what-have-you. You'll need to approach the code with only refactoring in mind, until it's clean enough that you can tell where the next piece of logic should go.
I'm new to ASP.Net MVC, so I try to find coding conventions for me, too:
write <% %> tags in a separate line (except for <%: and <%=)
eliminate sequences of %><% (except for <%: and <%=)
keep C# and HTML indentation separate
indent <%= and <%: as if they where HTML tags (if they do represent HTML tag/s)
I'm not a ASP expert, but like in PHP isn't there a way to echo things? In place of using so much open and close tags? I should place everything above the code, and make variables that you use in your HTML?
In my opinion, this isn't awful. I think the key here would be to try to spend some time walking through it and commenting where blocks start and then their corresponding end tags. It'll be painful now, but it'll save you some time later on.
I'm assuming you're looking for a code review. In that case:
remove the empty ELSE block with the comment "nothing, it appears"
Combine the nested IF conditions into a single check IF( count != 0 && count < 5 )
I'm studying ASP MVC, and developping SportsStore (Create/Edit feature). When Create a product, Create action will view a Edit view, but when press Sudmit, it call action Create (Post), althrough I will set it call Edit action:
<% using (Html.BeginForm("Edit", "Admin", FormMethod.Post, new { enctype="multipart/form-data" }))
{%>
<%--<%= Html.ValidationSummary() %>--%>
<%--<%= Html.Hidden("ProductID") %>--%>
<p>Name: <%= Html.TextBox("Name")%>
<div><%= Html.ValidationMessage("Name")%></div>
</p>
<p>Description: <%= Html.TextArea("Description", null, 4, 20, null)%>
<div><%= Html.ValidationMessage("Description")%></div>
</p>
<p>Price: <%= Html.TextBox("Price")%>
<div><%= Html.ValidationMessage("Price")%></div>
</p>
<p>Category: <%= Html.TextBox("Category")%>
<div><%= Html.ValidationMessage("Category")%></div>
</p>
<p>
Image:
<% if (Model.ImageData == null)
{ %>
None
<% }
else
{ %>
<img src= "<%= Url.Action("GetImage", "Products", new {Model.ProductID}) %>" />
<% } %>
<div>Upload new image: <input type="file" name="file" id="file" /></div>
</p>
<input type="submit" value="Save" />
<%= Html.ActionLink("Cancel and return to list", "Index")%>
<% } %>
Please help me fix it
The code you have seems reasonable if you want it to post back to the Edit action. Your question is a bit confusing, but I'm going to assume that you want to reuse the view and have it post back to Create when rendered from Create and Edit when rendered from Edit. The easiest way is to simply omit the parameters from the BeginForm call. This will cause the form action to be set to the current controller and action, which would give you what you seem to want. An alternative would be to develop templates (display/editor) for the model but have separate views for Create/Edit that simply render the template Html.EditorFor( m => m, "ProductTemplate" ). This would allow you to customize the view -- perhaps the Create view requires you to upload an image? -- yet still reuse most of the code.
Is there a way to include a VBScript page into an ASP page written using Javascript?
There is an ASP page written in Javascript, but our sidebar menu is written in VBScript. When I include the sidebar asp file into the Javascript the server gives an error.
< %# LANGUAGE="JavaScript" %>
<%
...
< !--#include file="sidebar.asp"-->
...
where sidebar.asp is written using VBScript.
You can try this, but my guess is that the sidebar.asp will be executed before your Javascript code.
< %# LANGUAGE="JavaScript" %>
<%
...
<script language="VBscript" runat=server>
< !--#include file="sidebar.asp"-->
</script>
...
I do this all the time, but I write my ASP/JScript pages a bit differently. Instead of switching the page language to "JavaScript", I leave it at the default "VBScript" and then use a <SCRIPT LANGUAGE="JavaScript" RUNAT="Server"> block for my JScript code. The JavaScript SCRIPT blocks are executed before the normal <% %> tags, so I do all my page processing in the SCRIPT blocks and then simply plug the results into the page with <% %> tags. Here's an example:
mainpage.asp:
<SCRIPT LANGUAGE="JavaScript" RUNAT="Server">
var name;
var address;
var phone;
function main() {
var rec = go_to_database();
name = rec.first_name + " " + rec.last_name;
address = rec.address;
phone = rec.phone;
}
</SCRIPT><% main() %>
<html><head><title><%= name %></title></head><body>
<p>Name: <%= name %><br/>
Address: <%= address %><br/>
Phone Number: <%= phone %></p>
<!--#include file="subpage.asp"-->
</body></html>
subpage.asp:
<p>Blah blah blah, some random VBScript code: <%
Dim whatever
whatever = some_silly_thing()
Response.Write(whatever)
%>.</p>
So, first IIS processes the SSI and includes subpage.asp into mainpage.asp. Then, it evaluates the JScript SCRIPT block, declaring the variables name, address, and phone and defining the function main.
Then it evaluates each <% %> tag in order. <% main() %> call the main function and sets values for name, address, and phone. Then <%= name %>, <%= address %>, and <%= phone %> substitute those values into the page. Finally, the <% %> code from subpage.asp is evaluated and the Response.Write value ends up in the page output.
While the whole page is not written in JScript, the vast majority of the code can be, inside the SCRIPT block. Would that work for you?