随笔 - 289  文章 - 1  评论 - 2716  阅读 - 195万

asp.net mvc(四)

     我在asp.net mvc (三) 中有类似如下的问题:有一个Partial View控件,在home这个view中使用该控件,怎么取key和value??就是在Partial View控件如何向View传值。

     我当时说到ViewData的应用,但ViewData 局限于当前Action。现在有了TempData后,一切都解决了。

     解决方案:修改生成留言的Action:这里给一个TempData赋值。

复制代码
[AcceptVerbs(HttpVerbs.Post)]
       
public ActionResult Create(GuestBookInfo model)
       {
           
try
           {
               inter.Add(model);
               var  models 
= inter.FindAllInfo();
               TempData[
"TempData"= "已经成功创建";
               
return RedirectToAction("Index");
           }
           
catch(Exception ex)
           {
               ModelState.AddModelError(
"ex",ex);
               
return View(model);

           }
       }  
复制代码

 

        然后在index View 就可以方便的访问下面的值:<%=TempData["TempData"]%>,有趣的是当TempData["TempData"]没有赋值时,这条语句并不会出错。


        我们来看下Controller之间为什么可以通过TempData来实现传值,在传统的asp.net 中我们经常会利用Session或者是Cookie来传值,TempData因为并不是通过网页参数传值,所以肯定是把数据存储在某个地方的原因。

        第一:查看Controller类的源码,其中包含一个重要的方法:在这个方面开始前就调用了基类的TempData.Load方法。

复制代码
protected override  void ExecuteCore()
{
    
base.TempData.Load(base.ControllerContext, this.TempDataProvider);
    
try
    {
        
string requiredString = this.RouteData.GetRequiredString("action");
        
if (!this.ActionInvoker.InvokeAction(base.ControllerContext, requiredString))
        {
            
this.HandleUnknownAction(requiredString);
        }
    }
    
finally
    {
        
base.TempData.Save(base.ControllerContext, this.TempDataProvider);
    }
}
复制代码

  
       第二:TempData.Load方法:可以看到最终是由ITempDataProvider这个接口来完成。

复制代码
public void Load(ControllerContext controllerContext, ITempDataProvider tempDataProvider)
{
    IDictionary
<stringobject> dictionary = tempDataProvider.LoadTempData(controllerContext);
    
this._data = (dictionary != null? new Dictionary<stringobject>(dictionary, 

StringComparer.OrdinalIgnoreCase) : 
new Dictionary<stringobject>(StringComparer.OrdinalIgnoreCase);
    
this._initialKeys = new HashSet<string>(this._data.Keys);
    
this._modifiedKeys.Clear();
}

复制代码

   
      第三:ITempDataProvider:我们可以在第一条中的代码中发现,接口是这样取的:

复制代码
public ITempDataProvider TempDataProvider
{
    
get
    {
        
if (this._tempDataProvider == null)
        {
            
this._tempDataProvider = new SessionStateTempDataProvider();
        }
        
return this._tempDataProvider;
    }
    
set
    {
        
this._tempDataProvider = value;
    }
}
复制代码


        第四:SessionStateTempDataProvider,从这个名字我们就可以猜测,数据应该是用Session方式保存。主要包含了两个方法,分别用于加载数据和保存数据。

复制代码
public virtual IDictionary<stringobject> LoadTempData(ControllerContext controllerContext)
{
    HttpContextBase httpContext 
= controllerContext.HttpContext;
    
if (httpContext.Session == null)
    {
        
throw new InvalidOperationException(MvcResources.SessionStateTempDataProvider_SessionStateDisabled);
    }
    Dictionary
<stringobject> dictionary = httpContext.Session["__ControllerTempData"as Dictionary<string

object>;
    
if (dictionary != null)
    {
        httpContext.Session.Remove(
"__ControllerTempData");
        
return dictionary;
    }
    
return new Dictionary<stringobject>(StringComparer.OrdinalIgnoreCase);
}

public virtual void SaveTempData(ControllerContext controllerContext, IDictionary<stringobject> values)
{
    HttpContextBase httpContext 
= controllerContext.HttpContext;
    
if (httpContext.Session == null)
    {
        
throw new InvalidOperationException(MvcResources.SessionStateTempDataProvider_SessionStateDisabled);
    }
    httpContext.Session[
"__ControllerTempData"= values;
}

复制代码

  
      小结:TempData虽然用Session来实现数据的存储,但对服务器来讲,代价虽然有,但并不高,因为从代码上看TempData用完一次就会被消除掉。看到这,我们可以想,是否可以看定义一个TempDataProvider,当然可以。这里我创建一个示例,并没有做功能上的改变,可以根据实际情况修改:

      1:创建MyTempDataProvider,让它继承ITempDataProvider ,并且实现LoadTempData和SaveTempData。
 
      2:将MyTempDataProvider与Controller联系上,我们可以选择扩展默认控制器工厂(DefaultControllerFactory) ,重写IController CreateController方法:

复制代码
public override IController CreateController(RequestContext requestContext, string controllerName)
        {
            Controller controller 
= base.CreateController(requestContext, controllerName) as Controller ;
            
if (null != controller)
            {
                controller.TempDataProvider 
= new MyTempDataProvider();
            }
            
return controller;

        }

复制代码

   
       3:注册我们自定义的MyControllerFactory,这也是最后一步。

复制代码
protected void Application_Start()
        {
            ControllerBuilder.Current.DefaultNamespaces.Add(
"GuestBook.MVC.Controller");
            ModelBinders.Binders.Add(
typeof(GuestBookInfo ), new GuestBookBinder ());
            ControllerBuilder.Current.SetControllerFactory(
typeof(MyControllerFactory ));
            RegisterRoutes(RouteTable.Routes);
        }
复制代码


        总结:通过了解TempData的实现机制以及生命周期,我们就不难实现我之前的难题了。

        注:本文参考:http://www.cnblogs.com/tristanguo/archive/2009/04/12/1433462.html
 

posted on   min.jiang  阅读(3116)  评论(4编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
历史上的今天:
2008-08-11 老生常谈:外观模式
2006-08-11 关于Microsoft索引服务设计
< 2009年8月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示