asp.net mvc 实现记忆返回的功能

大体思路是在当前跳转链接追加一个参数memoryguid,以guid为key把查询query保存在cookie里,跳转的时候带走这个guid,回来的时候还带着,这样我们就能根据这个guid从cookie里获取我们的query了.思路确定了,根据实际的情况实现适合自己的代码就行了,我们index是主页,list是一个分部页,因此我定义了两个Attribute来搞定这件事,代码如下:

public class MemoryGoAttribute : ActionFilterAttribute
{

    private readonly string _queryName;

    /// <summary>
    /// 保存的查询实体的参数名称
    /// </summary>
    /// <param name="queryName"></param>
    public MemoryGoAttribute(string queryName)
    {
        _queryName = queryName;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var parameters = filterContext.ActionParameters;
        if (!string.IsNullOrEmpty(_queryName))
        {
            object queryModel;
            var flag = parameters.TryGetValue(_queryName, out queryModel);
            if (flag)
            {
                //生成唯一标识  area controller action
                //var uniqueId = Guid.NewGuid().ToString("N");
                var uniqueId = filterContext.RouteData.DataTokens["area"].ToString()
                    + filterContext.RouteData.Values["controller"].ToString()
                    + filterContext.RouteData.Values["action"].ToString();
                uniqueId = uniqueId.ToLower();
                //将唯一标识添加到RouteData              
                filterContext.RouteData.Values.Add("memoryguid", uniqueId);
                //存入cookie
                var json = JsonConvert.SerializeObject(queryModel);
                CookieHelper.ClearCookie(uniqueId);
                var cookieHelper = CookieHelper.AddCookie(uniqueId, json, iDays: 0, iHours: 1);
            }
        }
        base.OnActionExecuting(filterContext);
    }
}

上边是在list上应用的特性,下边是应用在index上的特性

public class MemoryBackAttribute : ActionFilterAttribute
{
    private readonly Type _queryType;
    /// <summary>
    /// 查询实体的类型
    /// </summary>
    /// <param name="queryType"></param>
    public MemoryBackAttribute(Type queryType)
    {
        _queryType = queryType;
    }
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var queryString = filterContext.HttpContext.Request.QueryString;
        var uniqueId = queryString.Get("memoryguid");
        if (!string.IsNullOrEmpty(uniqueId))
        {
            var json = CookieHelper.GetCookie(uniqueId.ToString());
            if (!string.IsNullOrEmpty(json))
            {

                var dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
                //dic to obj
                var obj = Activator.CreateInstance(_queryType);
                foreach (var prop in _queryType.GetProperties())
                {
                    object value;
                    if (dic.TryGetValue(prop.Name, out value))
                    {
                        var type = prop.PropertyType;
                        //把数据转换成指定的类型,                               
                        prop.SetValue(obj, ChangeType(value, type), null);
                    }
                }

                filterContext.Controller.ViewBag.MemoryObj = obj;

                //dic to url: key=value&key=value
                var url = new StringBuilder();
                dic.Keys.ToList().ForEach(key => { url.AppendFormat("{0}={1}&", key, dic[key]); });

                filterContext.Controller.ViewBag.MemoryStr = url.ToString();
            }
        }
        base.OnActionExecuting(filterContext);
    }

    //转换成指定的类型
    private object ChangeType(object obj, Type type)
    {
        //判断type类型是否为泛型,因为nullable是泛型类,  
        if (type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
        {
            //如果type为nullable类,声明一个NullableConverter类,该类提供从Nullable类到基础基元类型的转换  
            System.ComponentModel.NullableConverter nullableConverter = new System.ComponentModel.NullableConverter(type);
            //将type转换为nullable对的基础基元类型  
            type = nullableConverter.UnderlyingType;
        }
        try
        {
            return Convert.ChangeType(obj, type, CultureInfo.InvariantCulture);
        }
        catch (Exception)
        {
            //不能转换
            return null;
        }
    }
}

然后页面上的链接需要将我们的这个guid追加上去,因此我写了个UrlHelper的扩展方法

public static class UrlHelperExtension
{        
    public static string MemoryAction(this UrlHelper url, string actionName, string controllerName, object routeValues)
    {
        var originalUrl = url.Action(actionName, controllerName, routeValues);

        var concat = originalUrl.Contains("?") ? "&" : "?";

        object uniqueId;
        //从RouteData中获取
        var routeData = url.RequestContext.RouteData.Values;
        if (routeData.TryGetValue("memoryguid", out uniqueId))
        {
            return string.Format(originalUrl + "{0}memoryguid={1}", concat, uniqueId);
        }
        //从QueryString中获取
        var queryString = url.RequestContext.HttpContext.Request.QueryString;
        uniqueId = queryString.Get("memoryguid");
        if (uniqueId != null)
        {
            return string.Format(originalUrl + "{0}memoryguid={1}", concat, uniqueId);
        }

        return originalUrl;
    }
}

这样就大功告成了,我的实际应用是这样的

[MemoryBack(typeof(QueryModel))]
public ActionResult Index()
{

}

[MemoryGo("query")]
public PartialViewResult List(QueryModel query)
{

}

<a href="Url.MemoryAction("action","controller",new{})" />

以上都是自己现在能想到,如果你们还有其它更好的思路和实现,请不要吝啬告诉我啊

posted @ 2016-12-22 11:58  BornReady  阅读(253)  评论(0编辑  收藏  举报