What's the best way to show a random image in ASP.NET? - asp.net

What I am talking about is like this website :
http://www.ernesthemingwaycollection.com
It has a static wallpaper and a set of images that change from page to page, I want to implement a similar way of displaying random images from a set of images using ASP.NET.
EDIT : I want the image to stay the same in a session, and change from a session to another.

The site you mentioned is not using a random set of images. They are coded into the html side of the aspx page.
You could place an asp Image control on your page. Then on the page's Page_Load function set the image to a random picture of your set.
protected void Page_Load(object sender, EventArgs e)
{
this.Image1.ImageUrl = "~/images/random3.jpg";
}
You have different options on where to store the image set data. You could use a database and store the urls in a table. This would allow to use the built-in Random function found in SQL. Or you can save a XML file to the server, load that then use the Random .Net class to pick one of your xml nodes.
Personally i would recommend the Database solution.
EDIT: Because the server session is destroyed after 20mins you may want to look at using cookies so you can see the last random image they saw.

If you just want to rotate a set number of images you could use the ASP.NET AdRotator control (at last, a use for it!).
If you want to do something fancier, considering using a jQuery slideshow such jQuery Cycle Plugin. There is also a slideshow control in the AjaxControlToolkit, which is easy to integrate.

string imageDir = "/images/banner/";
public static string chooseImage(string imageDir)
{
string[] dirs = Directory.GetFiles(HttpContext.Current.Server.MapPath("~/images/" + imageDir + "/"), "*.*");
Random RandString = new Random();
string fileFullPath = dirs[RandString.Next(0, dirs.Length)];
// Do not show Thumbs.db ---
string fileName = string.Empty;
do
{
fileName = System.IO.Path.GetFileName(fileFullPath);
} while (fileName.Contains(".db"));
string imgPath = "/images/" + imageDir + "/" + fileName;
return imgPath;
}
private int RandomNumber(int min, int max)
{
Random random = new Random();
return random.Next(min, max);
}

Related

ASP.NET -> How to POST data to the form such that images are displayed

Scenario : ASP.NET site has a page named ShowDesign.aspx.
ASPX page has lot of controls. I have a DIV tag and I load the images in code behind. DIV is defined something like below in the ASPX.
<div id="pImageHolder" runat="server"></div>
Below is the code behind that loads images.
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
//Loop inside PreviewImages which has lots of images.
foreach (String imgFile in this.PreviewImages)
{
Image pImage = new Image();
pImage.ImageUrl = imgFile; //URL length is longer. Do something.
this.pImageHolder.Controls.Add(pImage);
}
}
Update : Jun 1,2012 -> I have updated this question with more clarity as to what I am trying to do.
In OnInit(), I get the URL of the image (in the above loop). Every image will have unique URL.
Since the URL length of every image is longer, it doesn't display. The solution to this issue seems to be POSTING data to the form. The data that needs to be POSTED will be the URL contents.
The URL contains lot of '&' and I need to submit the contents of each '&' to the form.
Don't know if I need to use AJAX or Jquery here.
I need some help here to achieve the above.
Hope my question is clear. If not, please let me know.
According to latest comments, this question history and at the end you want post data to another url and get response html. Try this (I snipped your original url from previous question since is really big):
string strangeUrl = "http://example.com/is/m//company1/Rec-Sc-105-QL2?setAttr.safe={visible=false}&setAttr.insertedTextPlaceholder={visible=false}";
string data = strangeUrl.Substring(strangeUrl.IndexOf("?") + 1);
WebClient wc = new WebClient();
wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
string result = wc.UploadString("www.example.com/addres-for-post.aspx", data);

How can I place an ASP.NET menu control into cache?

I have a SharePoint2010 site that I have created an ASP.NET menu control for.
The ASP.NET menu's content is initially empty, and on Page_Load I load its content from standard HTML files on the server:
protected void Page_Init(object sender, EventArgs e)
{
string MenuPath = (string)ConfigurationSettings.AppSettings["RootMenuPath"].ToString();
Menu1.Items[0].ChildItems[0].Text = File.ReadAllText(MenuPath + "\\About.htm");
//etc...
}
I notice this is a horrible way to do things. It hits the disk every single time a user loads a page.
How can I either:
a) Cache the code and asp.net menu item so that it stays in memory?
b) Use another method to ensure it isn't loaded from the disk?
Thanks
You can wrap data load into property and use at least page Cache there:
readonly object cacheLock = new object();
string AboutHTM
{
get
{
if (Cache.Get("page.about") == null)
lock (cacheLock)
{
if (Cache.Get("page.about") == null)
Cache.Insert(File.ReadAllText(MenuPath + "\\About.htm"));
}
return Cache["page.about"].ToString();
}
}
You could indeed use the cache or some variable that is initialized only once in Application_Start and reused later but I am afraid that you are doing some premature optimization here. You probably shouldn't be doing it unless you have identified that this is a bottleneck for your application performance. Reading files from disk is a fast operation especially if they are small.
If possible, I would store the menu data in an XML file, and cache the XML file.
XmlDocument xDoc = new XmlDocument();
if (Cache.Get("MenuData") == null)
{
xDoc.Load(Server.MapPath("/MenuData.xml"));
Cache.Insert("SiteNav", xDoc, new CacheDependency(Server.MapPath("/MenuData.xml")));
}
else
{
xDoc = (XmlDocument)HttpContext.Current.Cache.Get("MenuData");
}

Asp.Net single control render for AJAX calls

I'm trying to implement something similar to this or this.
I've created a user control, a web service and a web method to return the rendered html of the control, executing the ajax calls via jQuery.
All works fine, but if I put something in the user control that uses a relative path (in my case an HyperLink with NavigateUrl="~/mypage.aspx") the resolution of relative path fails in my developing server.
I'm expecting:
http://localhost:999/MyApp/mypage.aspx
But I get:
http://localhost:999/mypage.aspx
Missing 'MyApp'...
I think the problem is on the creation of the Page used to load the control:
Page page = new Page();
Control control = page.LoadControl(userControlVirtualPath);
page.Controls.Add(control);
...
But I can't figure out why....
EDIT
Just for clarity
My user control is located at ~/ascx/mycontrol.ascx
and contains a really simple structure: by now just an hyperlink with NavigateUrl like "~/mypage.aspx".
And "mypage.aspx" really resides on the root.
Then I've made up a web service to return to ajax the partial rendered control:
[ScriptService]
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class wsAsynch : System.Web.Services.WebService
{
[WebMethod(EnableSession = true)]
public string GetControl(int parma1, int param2)
{
/* ...do some stuff with params... */
Page pageHolder = new Page();
UserControl viewControl = (UserControl)pageHolder.LoadControl("~/ascx/mycontrol.ascx");
Type viewControlType = viewControl.GetType();
/* ...set control properties with reflection... */
pageHolder.Controls.Add(viewControl);
StringWriter output = new StringWriter();
HttpContext.Current.Server.Execute(pageHolder, output, false);
return output.ToString();
}
}
The html is correctly rendered, but the relative path in the NavigateUrl of hyperlink is incorrectly resolved, because when I execute the project from developing server of VS2008, the root of my application is
http://localhost:999/MyApp/
and it's fine, but the NavigateUrl is resolved as
http://localhost:999/mypage.aspx
losing /MyApp/ .
Of Course if I put my ascx in a real page, instead of the pageHolder instance used in the ws, all works fine.
Another strange thing is that if I set the hl.NavigateUrl = Page.ResolveUrl("~/mypage.aspx") I get the correct url of the page:
http://localhost:999/MyApp/mypage.aspx
And by now I'll do that, but I would understand WHY it doesn't work in the normal way.
Any idea?
The problem is that the Page-class is not intented for instantiating just like that. If we fire up Reflector we'll quickly see that the Asp.Net internals sets an important property after instantiating a Page class an returning it as a IHttpHandler. You would have to set AppRelativeTemplateSourceDirectory. This is a property that exists on the Control class and internally it sets the TemplateControlVirtualDirectory property which is used by for instance HyperLink to resolve the correct url for "~" in a link.
Its important that you set this value before calling the LoadControl method, since the value of AppRelativeTemplateSourceDirectory is passed on to the controls created by your "master" control.
How to obtain the correct value to set on your property? Use the static AppDomainAppVirtualPath on the HttpRuntime class. Soo, to sum it up... this should work;
[WebMethod(EnableSession = true)]
public string GetControl(int parma1, int param2)
{
/* ...do some stuff with params... */
var pageHolder = new Page() { AppRelativeTemplateSourceDirectory = HttpRuntime.AppDomainAppVirtualPath };
var viewControl = (UserControl)pageHolder.LoadControl("~/ascx/mycontrol.ascx");
var viewControlType = viewControl.GetType();
/* ...set control properties with reflection... */
pageHolder.Controls.Add(viewControl);
var output = new StringWriter();
HttpContext.Current.Server.Execute(pageHolder, output, false);
return output.ToString();
}
The tildy pust the path in the root of the app, so its going to produce a the results you are seeing. You will want to use:
NavigateUrl="./whatever.aspx"
EDIT:
Here is a link that may also prove helpful...http://msdn.microsoft.com/en-us/library/ms178116.aspx
I find the /MyApp/ root causes all sorts of issues. It doesn't really answer your question 'why is doesn't work the normal way', but do you realize you can get rid of the /MyApp/ and host your website at http:/localhost/...?
Just set Virtual Path in the website properties to '/'.
This clears everything up, unless of course you are trying to host multiple apps on the development PC at the same time.
It might be that the new page object does not have "MyApp" as root, so it is resolved to the server root as default.
My question is rather why it works with Page.ResolveUrl(...).
Maybe ResolveUrl does some more investigation about the location of the usercontrol, and resolves based on that.
Weird, I recreated the example. The hyperlink renders as <a id="ctl00_hlRawr" href="Default.aspx"></a> for a given navigation url of ~/Default.aspx. My guess is that it has something to do with the RequestMethod. On a regular page it is "GET" but on a webservice call it is a "POST".
I was unable to recreate your results with hl.NavigateUrl = Page.ResolveUrl("~/mypage.aspx")
The control always rendered as <a id="ctl00_hlRawr" href="Default.aspx"></a> given a virtual path. (Page.ResolveUrl gives me "~/Default.aspx")
I would suggest doing something like this to avoid the trouble in the future.
protected void Page_Load(object sender, EventArgs e)
{
hlRawr.NavigateUrl = FullyQualifiedApplicationPath + "/Default.aspx";
}
public static string FullyQualifiedApplicationPath
{
get
{
//Return variable declaration
string appPath = null;
//Getting the current context of HTTP request
HttpContext context = HttpContext.Current;
//Checking the current context content
if (context != null)
{
//Formatting the fully qualified website url/name
appPath = string.Format("{0}://{1}{2}{3}",
context.Request.Url.Scheme,
context.Request.Url.Host,
(context.Request.Url.Port == 80 ? string.Empty : ":" + context.Request.Url.Port),
context.Request.ApplicationPath);
}
return appPath;
}
}
Regards,
It is hard to tell what you are trying to achieve without posting the line that actually sets the Url on of the HyperLink, but I think I understand your directory structure.
However, I have never run into a situation that couldn't be solved one way or another with the ResolveUrl() method. String parsing for a temporary path that won't be used in production is not recommended because it will add more complexity to your project.
This code will resolve in any object that inherits from page (including a usercontrol):
Page page = (Page)Context.Handler;
string Url = page.ResolveUrl("~/Anything.aspx");
Another thing you could try is something like this:
Me.Parent.ResolveUrl("~/Anything.aspx");
If these aren't working, you may want to check your IIS settings to make sure your site is configured as an application.

An image from byte to optimized web page presentation

I get the data of the stored image on database as byte[] array;
then I convert it to System.Drawing.Image like the code shown below;
public System.Drawing.Image CreateImage(byte[] bytes)
{
System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(bytes);
System.Drawing.Image image = System.Drawing.Image.FromStream(memoryStream);
return image;
}
(*) On the other hand I am planning to show a list of images on asp.net pages as the client scrolls downs the page. The more user gets down and down on the page he/she does see the more photos. So it means fast page loads and rich user experience. (you may see what I mean on www.mashable.com, just take care the new loads of the photos as you scroll down.)
Moreover, the returned imgae object from the method above, how can i show it in a loop dynamically using the (*) conditions above.
Regards
bk
Well, I think the main bottleneck is actually hitting the database each time you need an image. (Especially considering many users accessing the site.)
I would go with the following solution:
Database will store images with the original quality;
.ashx handler will cache images on the file system in various needed resolutions (like 32x32 pixels for icons, 48x48 for thumbnails, etc.) returning them on request and accessing database only once; (in this example is shown how to return an image via ashx handler)
The actual pages will point to .ashx page to get an image. (like <img scr="GetImage.ashx?ID=324453&Size=48" />)
UPDATE:
So the actual workflow in the handler will be like:
public void ProcessRequest (HttpContext context)
{
// Create path of cached file based on the context passed
int size = Int32.Parse(context.Request["Size"]);
// For ID Guids are possibly better
// but it can be anything, even parameter you need to pass
// to the web service in order to get those bytes
int id = Int32.Parse(context.Request["Id"]);
string imagePath = String.Format(#"images/cache/{0}/{1}.png", size, id);
// Check whether cache image exists and created less than an hour ago
// (create it if necessary)
if (!File.Exists(imagePath)
|| File.GetLastWriteTime(imagePath) < DateTime.Now.AddHours(-1))
{
// Get the file from the web service here
byte[] imageBytes = ...
// Save as a file
using (var memoryStream = new MemoryStream(imageBytes))
using (var outputStream = File.OpenWrite(imagePath))
Image.FromStream(memoryStream).Save(outputStream);
}
context.Response.ContentType = "image/png";
context.Response.WriteFile(imagePath);
}

Postback problem for my custom control load wizard

I have some problem that happens when controls are loaded in init and it still doesn't help me to get proper postback event fired on time.
I am trying to create a rich wizard control that will enable switching, links with description, completely customized steps, integration of substeps - by using dynamic control load that is avoids standard asp.net wizard way of loading.
Idea is to have on left part navigation, on right part content, or substeps that are run from right part and that go over whole area.
Download source project
Ok, I re-read the question, and here is what you have to do. You have to re-load these controls on each postback, give them always the same "Id". This can be done in Page_Init or in Page_Load event. And of course, you have to re-attach event handlers on each post back.
Many thanks.. well i found the answer - id was the problem, in load control method. I was doing this wizard.. well most of things work now.
If someone is interested to see how does this works.. there are some updates:
public void LoadSplitViewControl(string path)
{
SwitchNavigationView(NavigationView.SplitView);
LastNavigationView = NavigationView.SplitView;
LoadControl(SplitControlLoader, path, "LoadedControlSplit");
}
public void LoadSingleViewControl(string path)
{
SwitchNavigationView(NavigationView.SingleView);
LastNavigationView = NavigationView.SingleView;
LoadControl(SingleControlLoader, path, "LoadedControlSingle");
}
public void LoadSingleViewControlAsClear(string path)
{
SwitchNavigationView(NavigationView.SingleView);
LastNavigationView = NavigationView.SingleView;
LoadControlAsClear(SingleControlLoader, path, "LoadedControlSingle");
}
private void LoadControl(PlaceHolder holder, string path, string ID)
{
UserControl ctrl = (UserControl)Page.LoadControl(path);
ctrl.ID = ID;
LastControlPath = path;
holder.Controls.Clear();
holder.Controls.Add(ctrl);
}
//as i am using steps loaded controls using splitview and substeps controls using single view sometimes viewstate will not be valid so error will be thrown but u can resolve this by using LoadSingleViewControlAsClear that will load below method.
private void LoadControlAsClear(PlaceHolder holder, string path, string ID)
{
UserControl ctrl = (UserControl)Page.LoadControl(path);
ctrl.ID = ID;
LastControlPath = path;
ctrl.EnableViewState = false;
holder.Controls.Add(ctrl);
}
/another cool idea i am using for such an wizard is that i am not using viewstate but rather session object for saving values collected over steps. My session object key is generated by authenticated username and pageguid - so u can have many loaded pages and each of them will handle different session object./
public Guid PageGuid
{
get
{
if (PageGuidField.Value == "")
{
var _pageGuid = Guid.NewGuid();
PageGuidField.Value = _pageGuid.ToString();
return _pageGuid;
}
return new Guid(PageGuidField.Value);
}
}

Resources