PageRenderTime 51ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/wojilu/Web/Context/MvcContext.cs

https://bitbucket.org/kingshine/wojilu
C# | 775 lines | 387 code | 123 blank | 265 comment | 107 complexity | 43d3ed5918253db948a08ecbe507957a MD5 | raw file
Possible License(s): MIT
  1. /*
  2. * Copyright 2010 www.wojilu.com
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. using System;
  17. using System.Collections;
  18. using System.Collections.Specialized;
  19. using System.Collections.Generic;
  20. using System.Reflection;
  21. using System.Web;
  22. using wojilu.Data;
  23. using wojilu.ORM;
  24. using wojilu.Web.Mvc;
  25. using wojilu.Web.Mvc.Routes;
  26. using wojilu.Web.Utils;
  27. namespace wojilu.Web.Context {
  28. /// <summary>
  29. /// mvc 上下文数据:即整个执行流程中常用的数据封装
  30. /// </summary>
  31. public class MvcContext {
  32. private IWebContext _context;
  33. private MvcContextUtils _thisUtils;
  34. public MvcContext( IWebContext context ) {
  35. _context = context;
  36. _thisUtils = new MvcContextUtils( this );
  37. }
  38. /// <summary>
  39. /// 高级工具方法MvcContextUtils
  40. /// </summary>
  41. public MvcContextUtils utils {
  42. get {
  43. if (_thisUtils != null) return _thisUtils;
  44. _thisUtils = new MvcContextUtils( this );
  45. return _thisUtils;
  46. }
  47. }
  48. /// <summary>
  49. /// web 原始数据和方法封装
  50. /// </summary>
  51. public IWebContext web { get { return _context; } }
  52. private Result _errors = new Result();
  53. /// <summary>
  54. /// 获取当前ctx中的错误信息
  55. /// </summary>
  56. public Result errors { get { return _errors; } }
  57. /// <summary>
  58. /// 当前路由信息
  59. /// </summary>
  60. public Route route { get { return utils.getRoute(); } }
  61. /// <summary>
  62. /// 当前控制器
  63. /// </summary>
  64. public ControllerBase controller { get { return utils.getController(); } }
  65. /// <summary>
  66. /// 当前 owner(被访问的对象信息)
  67. /// </summary>
  68. public IOwnerContext owner { get { return utils.getOwnerContext(); } }
  69. /// <summary>
  70. /// 访问者的信息
  71. /// </summary>
  72. public IViewerContext viewer { get { return utils.getViewerContext(); } }
  73. /// <summary>
  74. /// 当前 app
  75. /// </summary>
  76. public IAppContext app { get { return utils.getAppContext(); } }
  77. private PageMeta _pageMeta = new PageMeta();
  78. /// <summary>
  79. /// 页面元信息(包括Title/Keywords/Description/RssLink)
  80. /// </summary>
  81. /// <returns></returns>
  82. public PageMeta GetPageMeta() {
  83. return _pageMeta;
  84. }
  85. //---------------------------------------------------------
  86. private Hashtable _contextItems = new Hashtable();
  87. /// <summary>
  88. /// 根据 key 获取存储在 ctx 中某项的值
  89. /// </summary>
  90. /// <param name="key"></param>
  91. /// <returns></returns>
  92. public Object GetItem( String key ) {
  93. return _contextItems[key];
  94. }
  95. /// <summary>
  96. /// 将某个对象存储在 ctx 中,方便不同的 controller 或 action 之间调用
  97. /// </summary>
  98. /// <param name="key"></param>
  99. /// <param name="val"></param>
  100. public void SetItem( String key, Object val ) {
  101. _contextItems[key] = val;
  102. }
  103. /// <summary>
  104. /// 判断 ctx 的存储器中是否具有某个 key 。
  105. /// </summary>
  106. /// <param name="key"></param>
  107. /// <returns></returns>
  108. public Boolean HasItem( string key ) {
  109. return _contextItems.ContainsKey( key );
  110. }
  111. //---------------------------------------------------------
  112. /// <summary>
  113. /// 获取链接对象
  114. /// </summary>
  115. /// <returns></returns>
  116. public Link GetLink() {
  117. return new Link( this );
  118. }
  119. private UrlInfo _url;
  120. /// <summary>
  121. /// 获取经过封装的 url 信息
  122. /// </summary>
  123. public UrlInfo url { get { return getUrl(); } }
  124. private UrlInfo getUrl() {
  125. if (_url == null) {
  126. _url = new UrlInfo( _context.Url, _context.PathApplication, _context.PathInfo );
  127. }
  128. return _url;
  129. }
  130. /// <summary>
  131. /// 设置当前网址,用于自定义网址
  132. /// </summary>
  133. /// <param name="url"></param>
  134. public void setUrl( String url ) {
  135. _url = new UrlInfo( url, _context.PathApplication, _context.PathInfo );
  136. }
  137. /// <summary>
  138. /// 当前客户端上传的所有文件
  139. /// </summary>
  140. /// <returns></returns>
  141. public List<HttpFile> GetFiles() {
  142. HttpFileCollection files = _context.getUploadFiles();
  143. List<HttpFile> list = new List<HttpFile>();
  144. for (int i = 0; i < files.Count; i++) {
  145. list.Add( new HttpFile( files[i] ) );
  146. }
  147. return list;
  148. }
  149. /// <summary>
  150. /// 当前客户端上传的第一个文件
  151. /// </summary>
  152. /// <returns></returns>
  153. public HttpFile GetFileSingle() {
  154. return this.GetFiles().Count == 0 ? null : GetFiles()[0];
  155. }
  156. /// <summary>
  157. /// 客户端是否上传了文件
  158. /// </summary>
  159. public Boolean HasUploadFiles {
  160. get { return GetFiles().Count > 0 && GetFileSingle().ContentLength > 10; }
  161. }
  162. /// <summary>
  163. /// 当前 ctx 中是否有错误信息
  164. /// </summary>
  165. public Boolean HasErrors {
  166. get { return errors.HasErrors; }
  167. }
  168. /// <summary>
  169. /// 客户端提交的 HttpMethod,返回GET/POST/DELETE/PUT 等
  170. /// </summary>
  171. public String HttpMethod { get { return getMethod(); } }
  172. /// <summary>
  173. /// 当前客户端提交方法是否是 GET 方法
  174. /// </summary>
  175. public Boolean IsGetMethod {
  176. get { return strUtil.EqualsIgnoreCase( "get", this.HttpMethod ); }
  177. }
  178. private String getMethod() {
  179. if ("POST".Equals( _context.post( "_httpmethod" ) )) return "POST";
  180. if ("DELETE".Equals( _context.post( "_httpmethod" ) )) return "DELETE";
  181. if ("PUT".Equals( _context.post( "_httpmethod" ) )) return "PUT";
  182. return _context.ClientHttpMethod;
  183. }
  184. private MethodInfo _actionMethodInfo;
  185. internal void setActionMethodInfo( MethodInfo mi ) {
  186. _actionMethodInfo = mi;
  187. }
  188. public MethodInfo ActionMethodInfo {
  189. get {
  190. if (_actionMethodInfo == null) {
  191. }
  192. return _actionMethodInfo;
  193. }
  194. }
  195. private List<Attribute> _attributes;
  196. public List<Attribute> ActionMethods {
  197. get {
  198. if (_attributes == null) {
  199. Object[] attrs = this.controller.utils.getAttributesAll( this.ActionMethodInfo );
  200. _attributes = new List<Attribute>();
  201. foreach (Object obj in attrs) {
  202. _attributes.Add( (Attribute)obj );
  203. }
  204. }
  205. return _attributes;
  206. }
  207. }
  208. /// <summary>
  209. /// 清理所有资源,准备抛出异常
  210. /// </summary>
  211. /// <param name="httpStatus">给客户端的 httpStatus 状态信息</param>
  212. /// <param name="msg"></param>
  213. /// <returns></returns>
  214. public MvcException ex( String httpStatus, String msg ) {
  215. utils.clearResource();
  216. return new MvcException( httpStatus, msg );
  217. }
  218. /// <summary>
  219. /// 呈现 json 到客户端
  220. /// </summary>
  221. /// <param name="jsonContent"></param>
  222. public void RenderJson( String jsonContent ) {
  223. _context.RenderJson( jsonContent );
  224. }
  225. /// <summary>
  226. /// 呈现 xml 到客户端
  227. /// </summary>
  228. /// <param name="xmlContent"></param>
  229. public void RenderXml( String xmlContent ) {
  230. _context.RenderXml( xmlContent );
  231. }
  232. //---------------------------------------- Get ---------------------------------------------
  233. /// <summary>
  234. /// 获取 url 中的某项值,结果已被过滤(不允许html)
  235. /// </summary>
  236. /// <param name="queryItem"></param>
  237. /// <returns></returns>
  238. public String Get( String queryItem ) {
  239. String val = _context.get( queryItem );
  240. return checkClientValue( val );
  241. }
  242. /// <summary>
  243. /// 检查 url 中是否具有某项 key
  244. /// </summary>
  245. /// <param name="key"></param>
  246. /// <returns></returns>
  247. public Boolean GetHas( String key ) {
  248. return _context.getHas( key );
  249. }
  250. /// <summary>
  251. /// 从 url 的查询信息 (query string) 中获取 id 列表,结果经过了验证,是类型安全的。如果不合法,则返回null
  252. /// </summary>
  253. /// <param name="idname"></param>
  254. /// <returns></returns>
  255. public String GetIdList( String idname ) {
  256. String ids = Get( idname );
  257. if (!cvt.IsIdListValid( ids )) {
  258. return null;
  259. }
  260. return ids;
  261. }
  262. /// <summary>
  263. /// 从 url 中获取某项的值,并转换成整数
  264. /// </summary>
  265. /// <param name="queryItemName"></param>
  266. /// <returns></returns>
  267. public int GetInt( String queryItemName ) {
  268. if ((_context.get( queryItemName ) != null) && cvt.IsInt( _context.get( queryItemName ) )) {
  269. return int.Parse( _context.get( queryItemName ) );
  270. }
  271. return 0;
  272. }
  273. /// <summary>
  274. /// 从 url 中获取某项的值,并转换成 Decimal
  275. /// </summary>
  276. /// <param name="queryItemName"></param>
  277. /// <returns></returns>
  278. public Decimal GetDecimal( String queryItemName ) {
  279. if ((_context.get( queryItemName ) != null)) {
  280. return cvt.ToDecimal( _context.get( queryItemName ) );
  281. }
  282. return 0;
  283. }
  284. /// <summary>
  285. /// 从 url 中获取某项的值,并转换成 Double
  286. /// </summary>
  287. /// <param name="queryItemName"></param>
  288. /// <returns></returns>
  289. public Double GetDouble( String queryItemName ) {
  290. if ((_context.get( queryItemName ) != null)) {
  291. return cvt.ToDouble( _context.get( queryItemName ) );
  292. }
  293. return 0;
  294. }
  295. /// <summary>
  296. /// 获取客户端 ip 地址
  297. /// </summary>
  298. public String Ip { get { return getIp(); } }
  299. private String getIp() {
  300. String ip;
  301. if (_context.ClientVar( "HTTP_VIA" ) != null)
  302. ip = _context.ClientVar( "HTTP_X_FORWARDED_FOR" );
  303. else
  304. ip = _context.ClientVar( "REMOTE_ADDR" );
  305. return checkIp( ip );
  306. }
  307. private String checkIp( String ip ) {
  308. int maxLength = 3 * 15 + 2;
  309. String unknow = "unknow";
  310. if (strUtil.IsNullOrEmpty( ip ) || ip.Length > maxLength || ip.Length < 7) return unknow;
  311. char[] arr = ip.ToCharArray();
  312. foreach (char c in arr) {
  313. if (!char.IsDigit( c ) && c != '.' && c != ',') return unknow;
  314. }
  315. return ip;
  316. }
  317. //------------------------------------------- POST ------------------------------------------
  318. /// <summary>
  319. /// 获取客户端 post 的值,结果已被过滤(不允许html)
  320. /// </summary>
  321. /// <param name="postItem"></param>
  322. /// <returns></returns>
  323. public String Post( String postItem ) {
  324. String val = _context.post( postItem );
  325. return checkClientValue( val );
  326. }
  327. /// <summary>
  328. /// 检查客户端 post 的数据中是否有某项 key
  329. /// </summary>
  330. /// <param name="key"></param>
  331. /// <returns></returns>
  332. public Boolean PostHas( String key ) {
  333. return _context.postHas( key );
  334. }
  335. /// <summary>
  336. /// 从客户端 post 的数据中获取某项的值,并转换成 decimal
  337. /// </summary>
  338. /// <param name="postItem"></param>
  339. /// <returns></returns>
  340. public Decimal PostDecimal( String postItem ) {
  341. if (_context.post( postItem ) != null) {
  342. return cvt.ToDecimal( _context.post( postItem ) );
  343. }
  344. return 0;
  345. }
  346. /// <summary>
  347. /// 从客户端 post 的数据中获取某项的值,并转换成 Double
  348. /// </summary>
  349. /// <param name="postItem"></param>
  350. /// <returns></returns>
  351. public Double PostDouble( String postItem ) {
  352. if (_context.post( postItem ) != null) {
  353. return cvt.ToDouble( _context.post( postItem ) );
  354. }
  355. return 0;
  356. }
  357. /// <summary>
  358. /// 从客户端 post 的数据中获取 id 列表,结果经过了验证,是类型安全的
  359. /// </summary>
  360. /// <param name="idname"></param>
  361. /// <returns></returns>
  362. public String PostIdList( String idname ) {
  363. String ids = Post( idname );
  364. if (!cvt.IsIdListValid( ids )) {
  365. return null;
  366. }
  367. return ids;
  368. }
  369. /// <summary>
  370. /// 从客户端 post 的数据中获取某项的值,并转换成整数
  371. /// </summary>
  372. /// <param name="postItem"></param>
  373. /// <returns></returns>
  374. public int PostInt( String postItem ) {
  375. if ((_context.post( postItem ) != null) && cvt.IsInt( _context.post( postItem ) )) {
  376. return int.Parse( _context.post( postItem ) );
  377. }
  378. return 0;
  379. }
  380. /// <summary>
  381. /// 检查客户端是否已经勾选了多选框,如果勾选返回1,否则返回0
  382. /// </summary>
  383. /// <param name="postItem"></param>
  384. /// <returns>如果勾选返回1,否则返回0</returns>
  385. public int PostIsCheck( String postItem ) {
  386. String target = Post( postItem );
  387. if (strUtil.HasText( target ) && target.Equals( "on" )) {
  388. return 1;
  389. }
  390. return 0;
  391. }
  392. /// <summary>
  393. /// 从客户端 post 的数据中获取某项的值,并转换成时间类型。如果无提交值或格式错误,则返回当前时间DateTime.Now
  394. /// </summary>
  395. /// <param name="postItem"></param>
  396. /// <returns></returns>
  397. public DateTime PostTime( String postItem ) {
  398. if (_context.post( postItem ) != null) {
  399. return cvt.ToTime( _context.post( postItem ) );
  400. }
  401. return DateTime.Now;
  402. }
  403. /// <summary>
  404. /// 获取客户端 post 的 html,结果已被过滤,只有在白名单中的 tag 才被允许
  405. /// </summary>
  406. /// <param name="postItem"></param>
  407. /// <returns></returns>
  408. public String PostHtml( String postItem ) {
  409. String val = _context.post( postItem );
  410. if (val != null) {
  411. if (this.viewer != null && this.viewer.IsAdministrator()) return val;
  412. val = strUtil.TrimHtml( val );
  413. val = HtmlFilter.Filter( val );
  414. }
  415. return val;
  416. }
  417. /// <summary>
  418. /// 获取客户端 post 的 html,结果已被过滤,只允许 allowedTags 中指定的 tag
  419. /// </summary>
  420. /// <param name="postItem"></param>
  421. /// <param name="allowedTags"></param>
  422. /// <returns></returns>
  423. public String PostHtml( String postItem, String allowedTags ) {
  424. String val = _context.post( postItem );
  425. if (val != null) {
  426. val = strUtil.TrimHtml( val );
  427. val = HtmlFilter.Filter( val, allowedTags );
  428. }
  429. return val;
  430. }
  431. /// <summary>
  432. /// 在默认白名单的基础上,允许 allowedTags 中指定的tag
  433. /// </summary>
  434. /// <param name="postItem"></param>
  435. /// <param name="allowedTags"></param>
  436. /// <returns></returns>
  437. public String PostHtmlAppendTags( String postItem, String allowedTags ) {
  438. String val = _context.post( postItem );
  439. if (val != null) {
  440. val = strUtil.TrimHtml( val );
  441. val = HtmlFilter.FilterAppendTags( val, allowedTags );
  442. }
  443. return val;
  444. }
  445. /// <summary>
  446. /// 允许接收客户端任意字符,请谨慎使用
  447. /// </summary>
  448. /// <param name="postItem"></param>
  449. /// <returns></returns>
  450. public String PostHtmlAll( String postItem ) {
  451. return _context.post( postItem );
  452. }
  453. //------------------------------------------- PARAMS ------------------------------------------
  454. /// <summary>
  455. /// 获取客户端提交的数据(包括get和post),结果已被过滤(不允许html)
  456. /// </summary>
  457. /// <param name="itemName"></param>
  458. /// <returns></returns>
  459. public String Params( String itemName ) {
  460. String val = _context.param( itemName );
  461. return checkClientValue( val );
  462. }
  463. /// <summary>
  464. /// 从客户端提交的数据中获取某项的值,并转换成整数
  465. /// </summary>
  466. /// <param name="postItem"></param>
  467. /// <returns></returns>
  468. public int ParamInt( String postItem ) {
  469. if ((_context.param( postItem ) != null) && cvt.IsInt( _context.param( postItem ) )) {
  470. return int.Parse( _context.param( postItem ) );
  471. }
  472. return 0;
  473. }
  474. /// <summary>
  475. /// 从客户端提交的数据中获取某项的值,并转换成 Decimal
  476. /// </summary>
  477. /// <param name="postItem"></param>
  478. /// <returns></returns>
  479. public Decimal ParamDecimal( String postItem ) {
  480. if (_context.param( postItem ) != null) {
  481. return cvt.ToDecimal( _context.param( postItem ) );
  482. }
  483. return 0;
  484. }
  485. /// <summary>
  486. /// 从客户端提交的数据中获取某项的值,并转换成 Double
  487. /// </summary>
  488. /// <param name="postItem"></param>
  489. /// <returns></returns>
  490. public Double ParamDouble( String postItem ) {
  491. if (_context.param( postItem ) != null) {
  492. return cvt.ToDouble( _context.param( postItem ) );
  493. }
  494. return 0;
  495. }
  496. //-------------------------------------------------------------------------------------
  497. /// <summary>
  498. /// 验证对象的各项属性是否合法
  499. /// </summary>
  500. /// <param name="target">需要被验证的对象</param>
  501. /// <returns>返回验证结果</returns>
  502. public Result Validate( IEntity target ) {
  503. return Validator.Validate( target );
  504. }
  505. /// <summary>
  506. /// 获取客户端post的数据,并自动赋值到对象各属性,最后进行验证
  507. /// </summary>
  508. /// <typeparam name="T"></typeparam>
  509. /// <returns></returns>
  510. public T PostValue<T>() {
  511. EntityInfo entityInfo = Entity.GetInfo( typeof( T ) );
  512. Type t = typeof( T );
  513. T obj = (T)rft.GetInstance( t );
  514. setObjectProperties( entityInfo, t, obj );
  515. IEntity entity = obj as IEntity;
  516. if (entity != null) {
  517. Result result = Validate( entity );
  518. if (result.HasErrors) errors.Join( result );
  519. }
  520. return obj;
  521. }
  522. /// <summary>
  523. /// 获取客户端post的数据,并自动赋值到对象各属性,最后进行验证
  524. /// </summary>
  525. /// <param name="obj"></param>
  526. /// <returns></returns>
  527. public Object PostValue( Object obj ) {
  528. EntityInfo entityInfo = Entity.GetInfo( obj );
  529. Type t = obj.GetType();
  530. setObjectProperties( entityInfo, t, obj );
  531. IEntity entity = obj as IEntity;
  532. if (entity != null) {
  533. Result result = Validate( entity );
  534. if (result.HasErrors) errors.Join( result );
  535. }
  536. return obj;
  537. }
  538. private void setObjectProperties( EntityInfo entityInfo, Type t, Object obj ) {
  539. String camelType = strUtil.GetCamelCase( t.Name );
  540. String prefix = camelType + ".";
  541. NameValueCollection posts = _context.postValueAll();
  542. foreach (String key in posts.Keys) {
  543. if (key.StartsWith( prefix ) == false) continue;
  544. String propertyName = strUtil.TrimStart( key, prefix );
  545. PropertyInfo p = t.GetProperty( propertyName );
  546. if (p == null) continue;
  547. if (entityInfo == null)
  548. setPropertyValue( obj, p, posts[key] );
  549. else {
  550. EntityPropertyInfo ep = entityInfo.GetProperty( propertyName );
  551. setEntityPropertyValue( obj, ep, posts[key] );
  552. }
  553. }
  554. }
  555. private String checkClientValue( String val ) {
  556. if (val != null) {
  557. val = val.Trim();
  558. val = HttpUtility.HtmlEncode( val );
  559. }
  560. return val;
  561. }
  562. private void setPropertyValue( Object obj, PropertyInfo p, String postValue ) {
  563. if (p.PropertyType == typeof( int )) {
  564. p.SetValue( obj, cvt.ToInt( postValue ), null );
  565. }
  566. else if (p.PropertyType == typeof( String )) {
  567. p.SetValue( obj, getAutoPostString( p, postValue ), null );
  568. }
  569. else if (p.PropertyType == typeof( Decimal )) {
  570. p.SetValue( obj, cvt.ToDecimal( postValue ), null );
  571. }
  572. else if (p.PropertyType == typeof( Double )) {
  573. p.SetValue( obj, cvt.ToDouble( postValue ), null );
  574. }
  575. else if (p.PropertyType == typeof( DateTime )) {
  576. p.SetValue( obj, cvt.ToTime( postValue ), null );
  577. }
  578. }
  579. private void setEntityPropertyValue( Object obj, EntityPropertyInfo p, String postValue ) {
  580. if (p.Type == typeof( int )) {
  581. p.SetValue( obj, cvt.ToInt( postValue ) );
  582. }
  583. else if (p.Type == typeof( String )) {
  584. p.SetValue( obj, getAutoPostString( p.Property, postValue ) );
  585. }
  586. else if (p.Type == typeof( Decimal )) {
  587. p.SetValue( obj, cvt.ToDecimal( postValue ) );
  588. }
  589. else if (p.Type == typeof( Double )) {
  590. p.SetValue( obj, cvt.ToDouble( postValue ) );
  591. }
  592. else if (p.Type == typeof( DateTime )) {
  593. p.SetValue( obj, cvt.ToTime( postValue ) );
  594. }
  595. else if (p.IsEntity) {
  596. IEntity objProperty = Entity.New( p.EntityInfo.FullName );
  597. objProperty.Id = cvt.ToInt( postValue );
  598. p.SetValue( obj, objProperty );
  599. }
  600. }
  601. private String getAutoPostString( PropertyInfo p, String postValue ) {
  602. Attribute htmlAttr = rft.GetAttribute( p, typeof( HtmlTextAttribute ) );
  603. if (htmlAttr == null) postValue = checkClientValue( postValue );
  604. return postValue;
  605. }
  606. private Boolean _isRunAction = true;
  607. internal void isRunAction( Boolean isRun ) {
  608. _isRunAction = isRun;
  609. }
  610. internal Boolean isRunAction() {
  611. return _isRunAction;
  612. }
  613. //------------------------------------------------------------------------------------
  614. private Link getLink() {
  615. return new Link( this );
  616. }
  617. /// <summary>
  618. /// 链接到某个 action
  619. /// </summary>
  620. /// <param name="action"></param>
  621. /// <returns></returns>
  622. public String to( aAction action ) {
  623. return getLink().To( action );
  624. }
  625. /// <summary>
  626. /// 链接到某个 action
  627. /// </summary>
  628. /// <param name="action"></param>
  629. /// <param name="id"></param>
  630. /// <returns></returns>
  631. public String to( aActionWithId action, int id ) {
  632. return getLink().To( action, id );
  633. }
  634. /// <summary>
  635. /// 链接到某个 action,网址中不包括 appId 信息
  636. /// </summary>
  637. /// <param name="action"></param>
  638. /// <returns></returns>
  639. public String t2( aAction action ) {
  640. return getLink().T2( action );
  641. }
  642. /// <summary>
  643. /// 链接到某个 action,网址中不包括 appId 信息
  644. /// </summary>
  645. /// <param name="action"></param>
  646. /// <param name="id"></param>
  647. /// <returns></returns>
  648. public String t2( aActionWithId action, int id ) {
  649. return getLink().T2( action, id );
  650. }
  651. }
  652. }