关于MVC中TempData悠久化难题

最近在做mvc跨调控器传值的时候开采一个主题素材,正是神迹候TempData的值为null,然后查阅了好些个材料,开采了广大都以逻辑和原理什么的(想看规律能够查阅原理的小说,本文是用法),但是真正消除的方法怎么案例都未曾,

前不久抽空看了眨眼间间ASP.NET MVC的一些源码,顺带写篇小说做个笔记以便日后查看。

本体系重大翻译自《ASP.NET MVC Interview Questions and Answers 》- By Shailendra Chauhan,想看意大利共和国语原版的可访谈活动下载。该书主要分为两有个别,ASP.NET MVC 5、ASP.NET WEB API2。本书最大的特点是以面试问答的款式开展扩充。通读此书,会协理你对ASP.NET MVC有越来越深档次的敞亮。
由于个人才具水平和德语水准也是轻松的,因而错误在所难免,希望大家多多留言指正。
洋洋洒洒导航
Asp.net mvc 知多少(一)
Asp.net mvc 知多少(二)
Asp.net mvc 知多少(三)
Asp.net mvc 知多少(四)
Asp.net mvc 知多少(五)

于是乎就把本身的代码当成案例给贴出来,方便越来越直观的缓慢解决问题。

在UrlRoutingModule模块中,将乞请管理程序映射到了MvcHandler中,因而,谈起Controller的激活,首先要从MvcHandler入手,MvcHandler达成了四个接口:IHttpAsyncHandler, IHttpHandler, IRequiresSessionState。 其拍卖逻辑主要完成在一块儿和异步的ProcessRequest方法中,总的来讲,该措施在举办的时候,差十分的少经历以下多少个步骤:

本节尤为重要讲明两种页面传值格局和http乞请与action的投射

因为TempData生命周期确实异常的短,所以供给悠久化一下:

  1. 预处理(在响应头中增多版本音信并剔除未赋值的可选路由参数)
  2. 透过ControllerBuilder获取ControlerFactory,并选拔Controller工厂创制Controller
  3. 依赖是或不是是异步管理,调用Controller中相应的章程(ExecuteCore或BeginExecute)
  4. 释放Controller

Q50. 介绍下ViewData, ViewBag, TempData 和 Session间的不相同之处?
Ans. 在ASP.NET MVC 中有三种艺术从controller传值到view中:ViewData, ViewBag 和 TempData。Asp.net WebForm 中得以在一遍客户会话中使用Session去长久化数据。

        public ActionResult Index()
        {
            TempData["message"] = "123asd";
            return view();
        }

        public ActionResult GetTemData()
        {
            var foredid = TempData["message"].ToString();
            var  result=_content.userinfo(foredid);
            return View();
        }

里头第一步在ProcessRequestInit方法中打开管理,本文重假若剖判第两步中的controller是何等制造出来的。

图片 1

在当前Action方法中调用Keep方法规有限援助在当下呼吁中TempData对象中所存储的键都不会被移除。

Controller的成立是通过ControllerFactory落成的,而ControllerFactory的创办又是在ControllerBuilder中做到的,由此大家先通晓一下ControllerBuilder的职业规律。

ViewData

 

ControllerBuilder

从源码中得以看出,在ControllerBuilder类中,并未直接促成对controller工厂的创办,ControllerFactory的创办实际上是寄托给贰个一而再自IResolver接口的SingleServiceResolver类的实例来贯彻的,那一点从GetControllerFactory方法中得以看看,它是通过调用SingleServiceResolver对象的Current属性来成功controller工厂的创导的。

public IControllerFactory GetControllerFactory()
{
    return _serviceResolver.Current;  //依赖IResolver接口创建工厂
}

相同的时间在源码中还发掘,SingleServiceResolver类是internal等级的,那表示外界不可能直接待上访谈,那么ControllerBuilder是如何依附Single瑟维斯Resolver来实现工厂的注册呢?继续看代码,ControllerBuilder类和SingleServiceResolver类皆有一个Func<IControllerFactory>花色的嘱托字段,我们姑且称为工厂委托,

//ControllerBuilder.cs
private Func<IControllerFactory> _factoryThunk = () => null;  //工厂委托
//SingleServiceResolver.cs
private Func<TService> _currentValueThunk;  //工厂委托

该信托达成了工厂的始建,而透过SetControllerFactory方法唯有是退换了ControllerBuilder类的厂子委托字段,并从未改观SingleServiceResolver类的工厂委托字段,

public void SetControllerFactory(IControllerFactory controllerFactory)
{
    if (controllerFactory == null)
    {
        throw new ArgumentNullException("controllerFactory");
    }

    _factoryThunk = () => controllerFactory;  //更改ControllerBuilder的工厂委托字段
}

由此必得将相应的转移应用到SingleServiceResolver类中手艺兑现真正的登记,大家清楚,若是是一味的引用赋值,那么退换二个援引并不会对别的一个引用产生更动,譬如:

Func<object> f1 = ()=>null;
Func<object> f2 = f1;  //f1与f2指向同一个对象
object o = new object();
f1 = ()=>o;  //更改f1后,f2仍然指向之前的对象
bool b1 = f1() == o;   //true
bool b2 = f2() == null;  //true,  f1()!=f2()

由此,ControllerBuilder在实例化SingleServiceResolver对象的时候,并未将小编的工厂委托字段直接赋值给SingleServiceResolver对象的附和字段(因为如此的话SetControllerFactory方法注册的信托不只怕运用到SingleServiceResolver对象中),而是经过信托来打开了打包,这样就能够产生二个闭包,在闭包中张开援用,如下所示:

Func<object> f1 = ()=>null;
Func<object> f2 = ()=>f1();  //通过委托包装f1,形成闭包
object o = new object();
f1 = ()=>o;  //更改f1后,f2与f1保持同步
bool b1 = f1() == o;  //true
bool b2 = f2() == o;  //true,  f1()==f2()

//ControllerBuilder.cs
internal ControllerBuilder(IResolver<IControllerFactory> serviceResolver)
{
    _serviceResolver = serviceResolver ?? new SingleServiceResolver<IControllerFactory>(
                                              () => _factoryThunk(),  //封装委托,闭包引用
                                              new DefaultControllerFactory { ControllerBuilder = this },
                                              "ControllerBuilder.GetControllerFactory");
}

如此SingleServiceResolver对象中的工厂委托就能够与ControllerBuilder对象中的对应字段保持同步了,SetControllerFactory方法也就到达了替换私下认可工厂的指标。

闭包援引测量试验代码:

using System;

class Program
{
    public static void Main(string[] args)
    {
        Func<object> f1 = ()=>null;
        Func<object> f2 = f1;  //f1与f2指向同一个对象
        object o = new object();
        f1 = ()=>o;  //更改f1后,f2仍然指向之前的对象
        bool b1 = f1() == o;   //true
        bool b2 = f2() == null;  //true,  f1()!=f2()

        Print("直接赋值:");
        Print(f1(),"f1() == {0}");
        Print(f2(),"f2() == {0}");
        Print(f1() == f2(),"f1() == f2() ? {0}");

        Func<object> ff1 = ()=>null;
        Func<object> ff2 = ()=>ff1();  //通过委托包装f1,形成闭包
        object oo = new object();
        ff1 = ()=>oo;  //更改f1后,f2与f1保持同步
        bool bb1 = ff1() == oo;  //true
        bool bb2 = ff2() == oo;  //true,  f1()==f2()

        Print("委托赋值:");
        Print(ff1(),"ff1() == {0}");
        Print(ff2(),"ff2() == {0}");
        Print(ff1() == ff2(),"ff1() == ff2() ? {0}");

        Console.ReadLine();
    }

    static void Print(object mess,string format = "{0}")
    {
        string message = mess == null ? "null" : mess.ToString();
        Console.WriteLine(string.Format(format,message));
    }
}

下边看一下Single瑟维斯Resolver类是怎么着完结指标的开创的,该类是个泛型类,那表示能够组织任何类型的靶子,不止限于ControllerFactory,实际上在MVC中,该类在众多地方都收获了选用,比方:ControllerBuilder、DefaultControllerFactory、BuildManagerViewEngine等,完结了对多样目的的创设。

  • ViewData 是一个承接自ViewDataDictionary类的字典对象。
    public ViewDataDictionary ViewData { get; set; }
  • ViewData 用来从controller中传值到相对应的view中。
  • 生命周期仅存在于方今此番乞请。
  • 假如发生重定向,那么值将会被清空。
  • 从ViewData中取值时需求开展类型调换和Null Check以避免相当。

总结:

SingleServiceResolver

此类实现了IResolver接口,首要用以提供内定项目标实例,在SingleServiceResolver类中有三种格局来创制对象:

1、private Lazy<TService> _currentValueFromResolver;  //内部调用_resolverThunk
2、private Func<TService> _currentValueThunk;  //委托方式
3、private TService _defaultValue;   //默认值方式

private Func<IDependencyResolver> _resolverThunk;  //IDependencyResolver方式

从Current方法中得以看出他们的早期级:

public TService Current
{
    get { return _currentValueFromResolver.Value ?? _currentValueThunk() ?? _defaultValue; }
}

_currentValueFromResolver实质上是对_resolverThunk的卷入,内部依然调用_resolverThunk来贯彻目的的组织,所以优先级是:_resolverThunk > _currentValueThunk > _defaultValue,即:IDependencyResolver情势> 委托形式 > 暗中同意值情势。

SingleServiceResolver在构造函数中默许实现了壹个DefaultDependencyResolver对象封装到委托字段_resolverThunk中,该暗中认可的Resolver是以Activator.CreateInstance(type)的章程成立对象的,不过有个前提,内定的type不可能是接口只怕抽象类,不然直接回到null。
在ControllerBuilder类中实例化SingleServiceResolver对象的时候内定的是IControllerFactory接口类型,所以其内部的SingleServiceResolver对象不可能通过IDependencyResolver格局制造对象,那么创制ControllerFactory对象的职分就达成了_currentValueThunk(委托方式)和_defaultValue(默许值情势)那多个法子上,前边说过,SingleServiceResolver类中的委托字段实际上是透过闭包引用ControllerBuilder类中的相应委托来创设对象的,而在ControllerBuilder类中,那么些相应的寄托私下认可是回到null,

private Func<IControllerFactory> _factoryThunk = () => null;

于是,暗中认可情状下SingleServiceResolver类的第三种办法也失效了,那么此时也不得不依赖暗中同意值情势来提供对象了,在ControllerBuilder类中那个私下认可值是DefaultControllerFactory:

internal ControllerBuilder(IResolver<IControllerFactory> serviceResolver)
{
    _serviceResolver = serviceResolver ?? new SingleServiceResolver<IControllerFactory>(
                                              () => _factoryThunk(),
                                              new DefaultControllerFactory { ControllerBuilder = this }, //默认值
                                              "ControllerBuilder.GetControllerFactory");
}

因而,在私下认可意况下是应用DefaultControllerFactory类来布局Controller的。
在创设SingleServiceResolver对象的时候,能够从多个地点剖断出真正创制对象的艺术是哪个种类:

new SingleServiceResolver<IControllerFactory>(   //1、看泛型接口,如果为接口或抽象类,则IDependencyResolver方式失效
    () => _factoryThunk(),  //2、看_factoryThunk()是否返回null,如果是则委托方式失效
    new DefaultControllerFactory { ControllerBuilder = this },  //3、以上两种都失效,则使用该默认值
    "ControllerBuilder.GetControllerFactory");

因此上述创制对象的经过能够获悉,有三种方法能够替换默许的靶子提供器:

  1. 轮换暗许的DependencyResolver,能够通过DependencyResolver类的静态方法SetResolver方法来落到实处:

    CustomDependencyResolver customResolver = new  CustomDependencyResolver();
    DependencyResolver.SetResolver(customResolver);
    

    将上述语句放在程序运行的地点,比方:Application_Start

  2. 透过前边介绍的ControllerBuilder类的SetControllerFactory方法

注:第一种艺术的先行级更加高。

ViewBag

1.当行使TempData对象存款和储蓄值而未调用TempData.Keep方法时,此时只要该指标被已读,然后该对象中的全数项将被标志为除去状态。

ControllerFactory

通过ControllerBuilder创立出ControllerFactory对象后,上面将在选用该指标完毕具体Controller的创立,ControllerFactory都达成了IControllerFactory接口,通超过实际现CreateController艺术成功对Controller的实例化,CreateController的里边逻辑特别轻易,就两步:获取Controller类型,然后创设Controller对象。

  • ViewBag ViewBag是二个动态属性,是基于C# 4.0的动态语言的表征。
    public Object ViewBag { get;}
  • 是对ViewData的二次包装,也是用来从controller中传值到相对应的view中。
  • 生命周期仅存在于近来本次诉求。
  • 假若发生重定向,那么值将会被清空。
  • 从ViewBag中取值时无需举行类型转换。

2.若调用TempData.Keep(string key)方法,此时不会开展标识。

获取Controller类型

逸事调整器名称获取调节器Type的历程,有须要浓厚摸底一下,以便于大家在后来超出相关主题素材的时候能够更加好的进展不当定位。获取项指标逻辑都封装在GetControllerType方法中,该进度根据路由数据中是还是不是包罗命名空间新闻,分为八个级次举办项目寻找:

  • 先是,借使当前路由数量中留存命名空间音信,则在缓存中依照调控器名称和命名空间寻觅对应的连串,借使找到唯一三个品种,则赶回该项目,找到多少个一贯抛卓殊
  • 其次,假如当前路由数量中不设有命名空间音信,或在率先级其余检索未有找到呼应的档案的次序,並且UseNamespaceFallback==true,此时会博得ControllerBuilder中装置的命名空间音讯,利用该新闻和调控器名称在缓存中进行项目寻找,假设找到独一两个品种,则赶回该项目,找到多少个一贯抛非凡
  • 最终,假如路由数据和ControllerBuilder中都尚未命名空间音信,只怕在以上多个品级都未曾寻觅到对应的Controller类型,那么会忽视命名空间,在缓存中仅依照调控器名称实行项目寻觅,倘使找到唯一三个类别,则赶回该项目,找到四个平素抛极度

为此,命名空间的预先级是:RouteData > ControllerBuilder

在缓存中寻觅类型的时候,假设是首先次搜索,会调用ControllerTypeCache.EnsureInitialized方法将保存在硬盘中的Xml缓存文件加载到贰个字典类型的内部存款和储蓄器缓存中。如果该缓存文件不真实,则会遍历当前选用援用的保有程序集,找寻具备public权限的Controller类型(决断标准:实现IController接口、非抽象类、类名以Controller结尾),然后将那么些类型音讯进行xml体系化,生成缓存文件保留在硬盘中,以便于下一次直接从缓存文件中加载,同期将类型消息分组以字典的花样缓存在内部存款和储蓄器中,进步找出频率,字典的key为ControllerName(不带命名空间)。

Controller类型寻觅流程如下图所示:

图片 2

TempData

3.RedirectToRouteResult和RedirectResult总是会调用TempData.Keep()方法,有限协助该指标中的全部项不会被移除。

创建Controller对象

收获Controller类型未来,接下去就要实行Controller对象的创建。在DefaultControllerFactory类的源码中能够见到,同ControllerBuilder类似,该类的构造函数中也实例化了三个SingleServiceResolver对象,依照事先介绍的章程,大家一眼就足以看看,该目的是行使暗许值的艺术提供了一个DefaultControllerActivator对象。

_activatorResolver = activatorResolver ?? new SingleServiceResolver<IControllerActivator>(  //1、泛型为接口,IDependencyResolver方式失效
                     () => null,  //2、返回了null,委托方式失效
                     new DefaultControllerActivator(dependencyResolver),  //3、以上两种方式均失效,则使用该提供方式
                     "DefaultControllerFactory constructor");

其实DefaultControllerFactory类仅完成了花色的搜索,对象的真的成立进度须求由DefaultControllerActivator类来达成,暗许意况下,DefaultControllerActivator成立Controller的经过是很简短的,因为它实在利用的是三个称呼DefaultDependencyResolver的类来打开Controller成立的,在这里类内部一贯调用Activator.CreateInstance(serviceType)办法成功目的的实例化。

从DefaultControllerFactory和DefaultControllerActivator那三个类的创建进程能够开采,MVC提供了多样办法(IDependencyResolver方式、委托格局、私下认可值格局)来提供对象,因而在对MVC相关模块进行扩张的时候,也可能有多样措施能够利用。

  • TempData 是三个持续于TempDataDictionary类的字典对象,存储于Session中 。
    public TempDataDictionary TempData { get; set; }
  • TempData 用来进展跨页面诉求传值。
  • TempData被呼吁后生命周期即甘休。
  • 从TempData中取值时供给进行类型转变和Null Check以幸免分外。
  • 重点用来囤积一遍性数据消息,比方error messages, validation messages。
    端详可参照:TempData知多少,
    Session
  • ASP.NET MVC中Session是Controller中的贰个属性,Session是HttpSessionStateBase类型。
    public HttpSessionStateBase Session { get; }
  • Session保存数据直到客商会话结束(暗中同意session过期时间为20mins)。
  • Session对具有的呼吁都灵验,不仅是纯净的跳转。
  • 从Session中取值时须求打开类型调换和Null Check以制止极度。

Controller中的数据容器

Controller中涉及到多少个给view传值的数码容器:TempData、ViewData和ViewBag。前两个的分歧之处在于TempData仅存款和储蓄临时数据,里面包车型地铁多少在率先次读取之后会被移除,即:只可以被读取贰遍;ViewData和ViewBag保存的是大同小异份数据,只可是ViewBag是动态指标,对ViewData举行了包装。

public dynamic ViewBag
{
    get
    {
        if (_dynamicViewDataDictionary == null)
        {
            _dynamicViewDataDictionary = new DynamicViewDataDictionary(() => ViewData); //封装ViewData
        }
        return _dynamicViewDataDictionary;
    }
}  

上边简单说一下TempData的贯彻原理。


TempData

率先看下MSDN上是怎么着解释的:

你可以按使用 ViewDataDictionary 对象的均等格局选拔 TempDataDictionary 对象传递数据。 不过,TempDataDictionary 对象中的数据仅从三个呼吁保持到下三个呼吁,除非你选用 Keep 方法将一个或五个键标志为需保留。 假设键已标识为需保存,则会为下多少个呼吁保留该键。
TempDataDictionary 对象的优异用法是,在数量重定向到三个操作方法时从另贰个操作方法传递数据。 比方,操作方法恐怕会在调用 RedirectToAction 方法以前,将有关错误的音讯囤积在调整器的 TempData 属性(该属性重临TempDataDictionary 对象)中。 然后,下贰个操作方法能够处理错误并显示呈现错误信息的视图。

TempData的风味正是能够在三个Action之间传递数据,它会保留一份数据到下一个Action,并乘胜再下二个Action的过来而失效。所以它被用在多个Action之间来保存数据,举例,那样二个现象,你的贰个Action接受一些post的数码,然后交到另二个Action来拍卖,并显示到页面,那时就足以采用TempData来传递那份数据。

TempData完成了IDictionary接口,同有的时候候中间含有一个IDictionary类型的私家字段,并增添了连带措施对字典字段的操作进行了决定,那鲜明是代理形式的贰个选用。因为TempData须求在Action之间传递数据,因而要求其能够对自己的多少开展封存,TempData信任ITempDataProvider接口实现了数量的加载与封存,暗许情状下是行使SessionStateTempDataProvider对象将TempData中的数据贮存在Session中。

下边看一下TempData是什么样调控数据操作的,TempDataDictionary源码中有与此相类似一段定义:

internal const string TempDataSerializationKey = "__tempData";

private Dictionary<string, object> _data;
private HashSet<string> _initialKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private HashSet<string> _retainedKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

私有字典字段_data是真的存放数据的地点,哈希集结_initialKeys和_retainedKeys用来标志数据,_initialKeys中贮存尚未被读取的数额key,_retainedKeys存放能够被频仍会见的key。
TempDataDictionary对数码操作的支配作为根本反映在在读取数据的时候并不会马上从_data中除去相应的多寡,而是经过_initialKeys和_retainedKeys那三个hashset标识每条数据的情事,最终在经过ITempDataProvider实行保存的时候再依照在此之前标识的事态对数据开展过滤,那时才去除已拜会过的数据。

有关的操纵措施有:TryGetValue、Add、Keep、Peek、Remove、Clear

1、TryGetValue

public bool TryGetValue(string key, out object value)
{
    _initialKeys.Remove(key);
    return _data.TryGetValue(key, out value);
}

该办法在读取数据的时候,会从_initialKeys集合中移除对应的key,前边说过,因为_initialKeys是用来标识数据未访谈状态的,从该会集中删除了key,之后在经过ITempDataProvider保存的时候就能将数据从_data字典中删除,下一遍呼吁就不能再从TempData访谈该key对应的数据了,即:数据只可以在一回呼吁中使用。

2、Add

public void Add(string key, object value)
{
    _data.Add(key, value);
    _initialKeys.Add(key);
}

增进多少的时候在_initialKeys中打上标识,注解该key对应的多寡能够被访谈。

3、Keep

public void Keep(string key)
{
    _retainedKeys.Add(key);
} 

调用Keep方法的时候,会将key增加到_retainedKeys中,声明该条记录能够被一再访问,为啥能够被反复探问呢,能够从Save方法中找到原因:

public void Save(ControllerContext controllerContext, ITempDataProvider tempDataProvider)
{
    // Frequently called so ensure delegate is stateless
    _data.RemoveFromDictionary((KeyValuePair<string, object> entry, TempDataDictionary tempData) =>
        {
            string key = entry.Key;
            return !tempData._initialKeys.Contains(key) 
                && !tempData._retainedKeys.Contains(key);
        }, this);

    tempDataProvider.SaveTempData(controllerContext, _data);
}

能够看见,在保留的时候,会从_data中抽取每一条数据,决断该数量的key是不是存在于_initialKeys和_retainedKeys中,借使都不设有才会从_data中移除,所以keep方法将key添加到_retainedKeys后,该多少就不会被去除了,即:能够在五个央求中被访谈了。

4、Peek

public object Peek(string key)
{
    object value;
    _data.TryGetValue(key, out value);
    return value;
}

从代码中可以看出,该措施在读取数据的时候,仅仅是从_data中展开了得到,并未移除_initialKeys集结中对应的key,因而通过该办法读取数据不影响多少的动静,该条数据还是得以在下贰回呼吁中被选拔。

5、Remove 与 Clear

public bool Remove(string key)
{
    _retainedKeys.Remove(key);
    _initialKeys.Remove(key);
    return _data.Remove(key);
}

public void Clear()
{
    _data.Clear();
    _retainedKeys.Clear();
    _initialKeys.Clear();
}

那四个点子没什么多说的,只是在剔除数据的时候还要删除其相应的情状。

Q51. 怎样悠久化TempData?
Ans. TempData的生命周期十三分指日可待,只可以存活到对象视图完全加载之后。
不过我们得以经过调用Keep措施去持久化TempData至下三遍访谈。

  • void Keep() - 调用这些办法将有限支撑此次央浼之后有所的TempData都将会被持久化。

    public ActionResult Index()
    {
     ViewBag.Message = TempData["Message"];
     Employee emp = TempData["emp"] as Employee; //need type casting
     TempData.Keep();//persist all strings values
     return View();
    }
    
  • void Keep(string key) - 调用那一个情势将确认保证此番央浼之后钦命的TempData会被漫长化。

    public ActionResult Index()
    {
     ViewBag.Message = TempData["Message"];
     Employee emp = TempData["emp"] as Employee; //need type casting
     //persist only data for emp key and Message key will be destroy
     TempData.Keep("emp");
     return View();
    }
    

Q52. ASP.NET MVC中怎么样支配session的表现?
Ans. 暗许ASP.NET MVC 扶助 session state(会话状态). Session用来积累跨央浼
里面包车型地铁数据。 不管你是或不是在session中储存数据,ASP.NET MVC都不能够不为具有的controller管理 session state,且是耗费时间的 。由此session是积攒在劳动器端的,消耗服务器的内部存款和储蓄器,所以料定影响你的应用程序的属性。 要是你的一点controller无需session调整,能够手动关闭session调控,来扩张微小的性质进步。
可以因此 session state的安顿项来简化它。
ASP.NET MVC4中的SessionState特点中,能够透过点名SessionStateBehavior枚举来完毕越来越多对session-state的支配。

  • Default :暗许的session state调控措施。
  • Disabled: Session state完全关闭。
  • ReadOnly:只读的session state。
  • Required:完全的可读写的 session state。

图片 3


Q53. ASP.NET MVC中 TempData与Session 有如何关系关系?
Ans. ASP.NET MVC中TempData使用session存款和储蓄跨央浼的一时半刻数据。由此,当你关闭了controller的session,当你去行使TempData时,就能够抛出以下极度。
图片 4


Q54. ASP.NET MVC中怎样是Action方法?
Ans. Controller中的action是概念在Controller类中的方法用来进行基于顾客央浼的操作,并在Model的协理下将结果传递会View。
Asp.net MVC 中合拢了以下二种ActionResults类型及相应的声援类情势:

  1. ViewResult - 使用Controller中提供的View()措施重返三个ViewResult用来突显钦赐或私下认可的View。
  2. PartialViewResult- 使用Controller中提供的PartialView()主意再次回到多少个PartialViewResult用来显现内定或暗许的总部视图。
  3. RedirectResult - 使用Controller中提供的Redirect()主意再次回到三个RedirectResult用来倡导三个HTTP 301 或 302 到钦点ULANDL的跳转。
  4. RedirectToRouteResult - 使用Controller中提供的RedirectToAction(), RedirectToActionPermanent(), RedirectToRoute(), RedirectToRoutePermanent()主意重回三个RedirectToRouteResult用来倡导二个HTTP 301或 302 到钦定action大概路由的跳转。
  5. ContentResult - 使用Controller中提供的Content()主意再次来到多少个ContentResult用来展现钦赐的公文。
  6. JsonResult - 使用Controller中提供的Json()办法再次来到贰个JsonResult用来展现类别化的Json格式数据。
  7. JavaScriptResult - 使用Controller中提供的JavaScript()办法再次回到三个JavaScriptResult用来显现一段JavaScript代码,经常仅用于Ajax诉求的光景。
  8. FileResult - 使用Controller中提供的File()办法再次回到贰个FileResult用来显示文件(PDF, DOC, Excel等)内容。
  9. EmptyResult - 再次回到二个空的结果。
  10. HttpNotFoundResult - 使用Controller中提供的HttpNotFound()措施重临两个HTTP 404境况。
  11. HttpUnauthorizedResult - 重返三个HttpUnauthorizedResult类型用来代表HTTP 401情景(未认证)。用来供给客商登陆以落成认证。
  12. HttpStatusCodeResult - 重回HttpStatusCodeResult用来代表钦命Http状态。

Q56. ASP.NET MVC中哪些标志Non-Action方法?
Ans. ASP.NET MVC 将具备的共用方法默以为action方法。
一旦不想有些公共的秘籍被暴光为Action,仅供给用NonActionAttribute标识方法就能够。

[NonAction]
public void DoSomething()
{
 // Method logic
}

Q57. 能或不可能更换Action方法的命名?
Ans. 能够因此ActionName特点来修改Action的命名。修改后Action将用ActionName中定义的名号被调用。

[ActionName("DoAction")]
public ActionResult DoSomething()
{
 //TODO:
 return View();
}

这样,DoSomething action就能够被会被标识为DoAction action。


Q58. 如何限制action仅能被相应的HTTP GET, POST, PUT or DELETE乞求访谈?
Ans. 暗中认可,每一个action方法都可以被别的HTTP要求访谈(i.e. GET, PUT, POST,
DELETE). 不过能够透过为action方法钦点HttpPost、 HttpPut 、 HttpDelete 性子来限制action的一颦一笑。

[HttpGet]
public ActionResult Index()
{
 //TODO:
 return View();
}

Q59. 怎么样调整一个action是被HTTP GET依然POST哀求?
Ans. 通过应用HttpRequestBase类的HttpMethod性子能够决断action是被哪类HTTP乞请调用。

public ActionResult Index(int? id)
{
 if (Request.HttpMethod == "GET")
 {
 //TODO:
 }
 else if (Request.HttpMethod == "POST")
 {
 //TODO:
 }
 else
 {
 //TODO:
 }
return View();
}

Q60. 什么样判别多个AJAX诉求?
Ans. 通过使用Request.IsAjaxRequest()来判断。

public ActionResult DoSomething()
{
 if (Request.IsAjaxRequest())
 {
 //TODO:
 }
 return View();
}

本文由星彩网app下载发布于计算机编程,转载请注明出处:关于MVC中TempData悠久化难题

TAG标签: 星彩网app下载
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。