示例#1
0
        /// <summary>
        /// If called from a "/submit" route, redirects to the *preceeding* route with the given message and the passed fields restored.
        ///
        /// If called from any other route type, this throws an exception.
        ///
        /// We fill values to be rendered into ViewData (after clearing it, for security purposes) to accomplish this.
        /// Anything that also appears in the target method signature will be set as a query parameter as well.
        ///
        /// So, if you call this from "/login/submit" with passBack = { username = "******" } it will render "/login" with ViewData["username"] = "******".
        /// message is stashed into ViewData["error_message"].
        ///
        /// Note that this method does not work from route with parameters in the path.
        /// </summary>
        public ActionResult RecoverableError(string message, object passBack)
        {
            const string submit = "/submit";

            var request = Current.RequestUri.AbsolutePath.ToLower();

            if (!request.EndsWith(submit))
            {
                throw new InvalidOperationException("Cannot recover from an error if a route isn't handling a POST");
            }

            var previousRoute = request.Substring(0, request.Length - submit.Length);

            var trueRandom = Current.UniqueId().ToString();

            var toStore = passBack.PropertiesAsStrings();

            toStore["error_message"] = message;

            Current.AddToCache(trueRandom, toStore, TimeSpan.FromMinutes(5));

            var queryString = "?recover=" + trueRandom;

            var route = RouteAttribute.GetDecoratedRoutes()[previousRoute.Substring(1)];

            foreach (var param in route.GetParameters())
            {
                if (toStore.ContainsKey(param.Name))
                {
                    queryString += "&" + param.Name + "=" + HttpUtility.UrlEncode(toStore[param.Name]);
                }
            }

            return(Redirect(previousRoute + queryString));
        }
示例#2
0
        /// <summary>
        /// Returns true if this is a valid vanity id.
        ///
        /// Doesn't check if the id has already been issued, or similar
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static bool IsValidVanityId(string id, out string errorMsg)
        {
            if (id.Length > 40)
            {
                errorMsg = "Vanity OpenId cannot be more than 40 characters long.";
                return(false);
            }

            if (!AllowedVanityIdRegex.IsMatch(id))
            {
                errorMsg = "Vanity OpenId can only contain letters, numbers, dashes, and periods.";
                return(false);
            }

            var existingRoutes = RouteAttribute.GetDecoratedRoutes().Keys.Select(k => k.ToLower());

            if (existingRoutes.Contains(id.ToLower()))
            {
                errorMsg = "This Vanity OpenId is reserved.";
                return(false);
            }

            // These two routes are manually mapped and *don't* contain illegal characters,
            //    so we need to check for them seperately
            if (id.ToLower() == "ping" || id.ToLower() == "report")
            {
                errorMsg = "This Vanity OpenId is reserved.";
                return(false);
            }

            errorMsg = null;
            return(true);
        }
示例#3
0
        /// <summary>
        /// Redirect to a given method (which is decorated with a RouteAttribute),
        /// with the given parameters.
        ///
        /// Lets us centralize all parameter encoding to reduce the odds of mistakenly
        /// passing things unencoded.  Also lets us catch re-named or unadorned routes
        /// a little easier.
        ///
        /// Makes it less tempting to resort to error prone string.Format() stuff everywhere
        /// too.
        ///
        /// Also, not that { Controller = "Blah", Action = "MoreBlah" } stuff that's just as nasty
        /// as string.Format IMO.
        ///
        /// Note does not work with routes with "in path" parameters, only query string passed
        /// parameters.
        ///
        /// As an aside, boy would it be handy if you could actually use MethodGroups for something,
        /// instead of just being a source of compiler errors.
        /// </summary>
        public RedirectResult SafeRedirect(Delegate target, object @params = null)
        {
            var toAction = target.Method;

            var routes = RouteAttribute.GetDecoratedRoutes();

            if (!routes.Values.Contains(toAction))
            {
                throw new ArgumentException("Method not decorated with RouteAttribute: " + toAction);
            }

            var registered = routes.Where(v => v.Value == toAction).Select(v => v.Key).Single();

            return(UnsafeRedirect(registered, @params));
        }