Dynamic download link algorithm - asp.net

I have seen a couple of websites that have a dynamic download link.
They ask for a valid email address and send the dynamically created download link to that address.
E.X. www.mysite.domain/hashvalue1
But how they do that, since the file exists on the domain in a specific location?
www.mysite.domain/downloads
Is there any guide around this?

They use "UrlRewrite" and a ASP.NET HttpHandler.
UrlRewrite: http://weblogs.asp.net/scottgu/archive/2007/02/26/tip-trick-url-rewriting-with-asp-net.aspx
Handler: Downlaod.ashx
using System;
using System.Web;
public class GetDownload : IHttpHandler
{
private static string file = "your file location";
public void ProcessRequest (HttpContext context)
{
if(UsersHasRights(context))
{
context.Response.TransmitFile(file);
}
}
public bool IsReusable
{
get { return false; }
}
}

Yes, Web URL does not have to correspond to the actual file location.
The easiest way to implement this in .NET is to create an IHttpHandler which uses Response.TransmitFile based on hash value.
In this case, URL would be www.mysite.domain/file.ashx?hash=hashvalue1.
You can get better URLs if you use Routing (ASP.NET 3.5 SP1) or some kind of URL rewriter.

This may not be most efficient or best way to do but can solve your problem. You have file at specific location on the server and you know it when user clicks or request for downloading. You get email address and together from file name or path and email create hash you can add some salt to it to really randomize it even if same user requests the same file again and again. Now put this hash, filename and salt (if you have one) into a database table. You can also have expirey date-time for link.
You can send user link like this site.com/files.dld?hash and implement IHttpHandler to handle this extension (see this answer by Andrey Shchekin). Here is also an article describing use of HttpHandler to provide download of zip files.

Related

Where the vales like Userid and passwords are stored in SSO of BTDF

I have a query regarding BTDF SSO config setting. I am beginner with BizTalk.
I am looking for SSO storage where credentials are stored and retrieved from SSO. I have built-in app located at C:\Program Files (x86)\Deployment Framework for BizTalk 6.0\Framework\DeployToolsork\DeployTools
Could anyone tell me how to store and retrieve from existing SSO config like SSOSettingsEditor which is the default provided by BTDF.
Using BTDF, you can store your configurations as provided in SettingsFileGenerator.xml in BizTalk SSODB. BTDF automatically store your configuration if IncludeSSO property is set to true in btdfproj file.
If you have provided your credential details in SettingsFileGenerator.xml file then only you will find them in SSODB.
You should use SSOSettingsEditor to retrieve or make changes to the configurations. In SSOSettingsEditor, type in your application name and press enter.
Refer to link: BTDF IncludeSSO
BTDF provides a library for modifying SSO Settings that it uses. The method is uses is slightly different from the default Microsoft sample SSO client, so take care regarding which one you're using.
Per that link, the class provides these methods:
namespace SSOSettingsFileManager
{
public static class SSOSettingsManager
{
public static void WriteSetting(string affiliateApplication, string propertyName, string propertyValue);
}
}
It should be fairly straightforward to call that method once you've added a reference to the SSOSettingsFileReader.dll in whatever C# project you have generating your password or updating it, i.e.
string newPassword = GenerateMyPassword();
SSOSettingsFileManager.SSOSettingsManager.WriteSetting("MyApplicationName", "Password", newPassword;);
You could also look at the source of how he's doing it if you want to implement the method yourself.

Check for a static file during Application_BeginRequest?

I have a Global.asx file that needs to do custom authentication, auditing and profiling stuff. This is needed because it supports a SAML based SSO system and needs to override the normal .Net authentication (which doesn't support either SAML or mixed authentication)
I don't want to fire it for static files, such as .js, .css, .png, etc
In Cassini/WebDev and IIS7 it does.
What I want to have is some simple check, like a this.Request.IsStaticFile (which doesn't exist, unfortunately) to identify the static files.
I realise that this would be fairly simple to write, but it feels like something that must already exist - IIS has already applied caching policy stuff for the static files and so on.
I need a code solution, rather than an IIS config change one.
Update
This is my current workaround:
/// <summary>Hold all the extensions we treat as static</summary>
static HashSet<string> allowedExtensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
".js", ".css", ".png", ...
};
/// <summary>Is this a request for a static file?</summary>
/// <param name="request">The HTTP request instance to extend.</param>
/// <returns>True if the request is for a static file on disk, false otherwise.</returns>
public static bool IsStaticFile(this HttpRequest request)
{
string fileOnDisk = request.PhysicalPath;
if (string.IsNullOrEmpty(fileOnDisk))
{
return false;
}
string extension = Path.GetExtension(fileOnDisk);
return allowedExtensions.Contains(extension);
}
This works and is quick enough, but feels horribly clunky. In particular relying on extensions is going to be error prone if we add new static files not thought of.
Is there a better way without changing the IIS config?
You might be able to check which handler is dealing with the request.
In IIS6 only .net files, eg aspx are mapped to a handler that does stuff.
In IIS7 with the integrated pipeline, everything routes through .net, which is normally a good thing. Different handlers still deal with different file types though. In particular I believe the staticfilehandler is the one you need to check for. The httpcontext.handler property should allow you to figure it out.
You could create an extension method to add that IsStatic method...
Simon
There are a few options:
Adding authorization element and deny none for those paths that you do not need any authentication and contains your static files
You are using integrated pipeline. Turn it off on your IIS 7.
There is no doubt that you need to create a custom extension method because ASP.NET routing engine uses this code to decide whether a file exist,
if (!this.RouteExistingFiles)
{
string appRelativeCurrentExecutionFilePath = httpContext.Request.AppRelativeCurrentExecutionFilePath;
if (((appRelativeCurrentExecutionFilePath != "~/") && (this._vpp != null)) && (this._vpp.FileExists(appRelativeCurrentExecutionFilePath) || this._vpp.DirectoryExists(appRelativeCurrentExecutionFilePath)))
{
return null;
}
}
You will not able to decide whether the request is static in Application_BeginRequest using context.handler because Routing Module may change the handler and this module always execute after Application_BeginRequest. My suggestion is to use the similar code which ASP.NEt routing engine uses.

ASP.NET Routing - GetRouteData does not work if path exists

I have a HttpModule which intercepts all requests and loads data from the database based on routing rules. However, I run into one problem all the time; GetRouteData only works if the path does not exist:
var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(HttpContext.Current));
Assuming a request comes in for the url http://localhost/contact, I get the correct routing data relating to that url if that path does not exist in the file system. The problem appears when I want to customize the page at that url which I do by creating an aspx page in the path ~/contact/default.aspx. Once I do that, GetRouteData return null.
I have even tried creating a new HttpContext object, but I still can not retrieve route data if the page exists.
Has anyone ever run into this problem? Is there a solution/workaround?
All help will be greatly appreciated.
Set RouteCollection.RouteExistingFiles to true.
public static void RegisterRoutes(RouteCollection routes)
{
// Cause paths to be routed even if they exists physically
routes.RouteExistingFiles = true;
// Map routes
routes.MapPageRoute("...", "...", "...");
}
Beware though. IIS7 behaves a little differently than the server used when debugging within Visual Studio. I got bit by this when I deployed my application to the web. Check out this feedback I submitted to Microsoft Connection.

ASP.NET: WebResource.axd call 404 error: how to know which assembly/resource is missing or responsible?

I get a 404 HTTP status error (not found) on a specific WebResource.axd call inside an ASP.NET 3.5 (AJAX) web application. I guess the error is thrown because a specific referenced assembly is missing in the bin folder/GAC. But I don't know which, since the page which requests the resource is very complex (I'm using third-party controls and ASP.NET Ajax.)
Is it possible to know from the encrypted "d" querystring parameter of the query, like:
.../WebResource.axd?d=...
which assembly should create the content and is possibly missing?
Note: There are other WebRequest.axd calls which execute with success.
One of the reasons for this issue is that the registered embedded resource path is incorrect or the resource is not there. Make sure the resource file is added as a Embedded Resource.
Asp.net uses the WebResourceAttribute which you must give the path to the resource.
The resource file needs to be added as a Embedded Resource to the project and the path to it would be the full namespace plus the file name.
So you have the following project resource "my.js" in the project "MyAssembly" the resource path would be "MyAssembly.my.js".
To check what file the web resource handler is not finding you can decrypt the hash code provided on the WebResource.axd url. Please see the example below an how to do that.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
namespace WebApplication1
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
byte[] encryptedData = HttpServerUtility.UrlTokenDecode("encoded hash value");
Type machineKeySection = typeof(System.Web.Configuration.MachineKeySection);
Type[] paramTypes = new Type[] { typeof(bool), typeof(byte[]), typeof(byte[]), typeof(int), typeof(int) };
MethodInfo encryptOrDecryptData = machineKeySection.GetMethod("EncryptOrDecryptData", BindingFlags.Static | BindingFlags.NonPublic, null, paramTypes, null);
try
{
byte[] decryptedData = (byte[])encryptOrDecryptData.Invoke(null, new object[] { false, encryptedData, null, 0, encryptedData.Length });
string decrypted = System.Text.Encoding.UTF8.GetString(decryptedData);
decryptedLabel.Text = decrypted;
}
catch (TargetInvocationException)
{
decryptedLabel.Text = "Error decrypting data. Are you running your page on the same server and inside the same application as the web resource URL that was generated?";
}
}
}
}
Original code example by Telerik UI for ASP.NET AJAX Team Link: http://blogs.telerik.com/aspnet-ajax/posts/07-03-27/debugging-asp-net-2-0-web-resources-decrypting-the-url-and-getting-the-resource-name.aspx
This should return the URL path that aspt.net believes the embedded resource is at.
I just spent hours on a similar issue. Due to the great article pointed out by Diadistis I was able to decrypt the WebResource url and find out that my WebResource was translated into a wrong assembly pointer, recognizable by the garbage in front of your resource name. After many struggles I found out that this was because I was using the Page.ClientScript.GetWebResourceUrl in a class deriving from another class which resided outside of the assembly my resource was in. Confusing thing was that my class WAS in the same assembly, though the class deriving from was NOT. The this.GetType() parameter many articles state is a must, turned out not to be so much of a must at all in my situation. Actually, it needed to be replaced with a typeof() and it worked! Hope this may prevent others from getting the same headache as I got from this bugger.
In my case, the source of the 404 error was that the date and time of the machine running IIS were wrong (from the past).
Is your project missing any references?
Are there any references set to CopyLocal=False (common with Infragistics or GAC'ed refs) that dont make it to the destination?
A utility like reflector or dependency walker will tell you if your main assembly is missing any dependencies that are not immediately obvious.
Does the Application_Error handler in global.asax have a catch that is producing any error info (FileNotFoundExceptions)?
Did you set custom errors to 'remote only' and browse the site from the local machine?
This same issue occurs if there is a request filtering rule that detects the specified string in the query string. In my case, the query string for the AXD file was generated with a double dash that the rule detected and caused a 404 not found error for the AXD file request.

asp.net mvc framework, automatically send e-mail

I want my asp.net mvc framework system to send an e-mail everytime a certain action (inside a certain controller) is fired off. Are there any third party libraries or .net standard ways to accomplish this?
A more up to date method would be to use System.Net.Mail - this is the 2.0 replacement for System.Web.Mail.
Something like this, called from either a BaseController (if there are other controllers that need this) the actual controller in question.
I have the following code inside a static class to handle mailing simple plain text items from the server:
internal static void SendEmail(MailAddress fromAddress, MailAddress toAddress, string subject, string body)
{
var message = new MailMessage(fromAddress, toAddress)
{
Subject = subject,
Body = body
};
var client = new SmtpClient("smtpServerName");
client.Send(message);
}
Obviously, you'd probably want some error handling etc in there - Send can throw an exception for example if the server is refusing connections.
Create a BaseController from which all your other controllers inherits.
In the BaseController override the OnActionExecuted Method and insert your code for sending the email.
public class BaseController : Controller
{
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
// Send mail here
base.OnActionExecuted(filterContext);
}
}
The SmtpClient Class with the other System.Net.Mail classes are easily utilized from any .NET program to send mail. You just need to point it to an available and willing SMTP server.
Well its not really hard to send a Email using .NET. You can just send the mail from inside your action.
But, I think we talk little about logging here, and for logging there is a range of 3th party libraries. I know there is one called Log4Net.
Most of these logging frameworks makes it possible to config how logs are stored, and porsibly also a setting to send a email, when it logs something.
But in your scenario, it would just write a plain simple mail function, that sends the mail, when the user enters the action. You can make look at: http://www.developer.com/net/asp/article.php/3096831 - its a demo of sending a mail using .NET - webforms though, but the basic things still apply to MVC.

Resources