nonatomic,assign,copy,retain的区别

mikel阅读(923)

nonatomic:非原子性访问,不加同步,多线程并发访问会提高性能。如果不加此属性,则默认是两个访问方法都为原子型事务访问。
(atomic是Objc使用的一种线程保护技术,基本上来讲,是防止在写未完成的时候被另外一个线程读取,造成数据错误。而这种机制是耗费系统资源的,所 以在iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。)

assign: 简单赋值,不更改索引计数
对基础数据类型 (NSInteger)和C数据类型(int, float, double, char, 等)

copy:建立一个索引计数为1的对象,然后释放旧对象
对NSString

retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1
对其他NSObject和其子类

copy与retain的区别:
copy是创建一个新对象,retain是创建一个指针,引用对象计数加1。
eg:   一个NSString 对象,地址为0×1111 ,内容为@”STR”

 

Copy 到另外一个NSString 之后,地址为0×2222 ,内容相同,新的对象retain为1 ,旧有对象没有变化

retain 到另外一个NSString 之后,地址相同(建立一个指针,指针拷贝),内容当然相同,这个对象的retain值+1

也就是说,retain 是指针拷贝,copy 是内容拷贝。

Objective-C中的@property和@synthesize用法

mikel阅读(991)

@代表“Objective-C”的标志,证明您正在使用Objective-C语言

Objective-C语言关键词,@property与@synthesize配对使用。

功能:让编译好器自动编写一个与数据成员同名的方法声明来省去读写方法的声明。

如:
1、在头文件中:
C代码 收藏代码
@property int count;
等效于在头文件中声明2个方法:
C代码 收藏代码
– (int)count;
-(void)setCount:(int)newCount;

2、实现文件(.m)中
C代码 收藏代码
@synthesize count;
等效于在实现文件(.m)中实现2个方法。
C代码 收藏代码
– (int)count
{
return count;
}
-(void)setCount:(int)newCount
{
count = newCount;
}

以上等效的函数部分由编译器自动帮开发者填充完成,简化了编码输入工作量。

格式:

声明property的语法为:@property (参数1,参数2) 类型 名字;

如:
C代码 收藏代码
@property(nonatomic,retain) UIWindow *window;

其中参数主要分为三类:

读写属性: (readwrite/readonly)
setter语意:(assign/retain/copy)
原子性: (atomicity/nonatomic)

各参数意义如下:

readwrite: 产生setter\getter方法
readonly: 只产生简单的getter,没有setter。
assign: 默认类型,setter方法直接赋值,而不进行retain操作
retain: setter方法对参数进行release旧值,再retain新值。
copy: setter方法进行Copy操作,与retain一样
nonatomic: 禁止多线程,变量保护,提高性能

参数类型
参数中比较复杂的是retain和copy,具体分析如下:

getter 分析

1、
C代码 收藏代码
@property(nonatomic,retain)test* thetest;
@property(nonatomic ,copy)test* thetest;
等效代码:
C代码 收藏代码
-(void)thetest
{
  return thetest;
}

2、
C代码 收藏代码
@property(retain)test* thetest;
@property(copy)test* thetest;
等效代码:
C代码 收藏代码
-(void)thetest
{
[thetest retain];
return [thetest autorelease];
}

setter分析

1、
C代码 收藏代码
@property(nonatomic,retain)test* thetest;
@property(retain)test* thetest;
等效于:
C代码 收藏代码
-(void)setThetest:(test *)newThetest {
if (thetest!= newThetest) {
   [thetestrelease];
   thetest= [newThetest retain];
}
}

2、
C代码 收藏代码
@property(nonatomic,copy)test* thetest;
@property(copy)test* thetest;
等效于:
C代码 收藏代码
-(void)setThetest:(test *)newThetest {
if (thetest!= newThetest) {
   [thetest release];
   thetest= [newThetest copy];
}
}

nonatomic
如果使用多线程,有时会出现两个线程互相等待对方导致锁死的情况(具体可以搜下线程方面的注意事项去了解)。在没有(nonatomic)的情况下,即默认(atomic),会防止这种线程互斥出现,但是会消耗一定的资源。所以如果不是多线程的程序,打上(nonatomic)即可

retain
代码说明
如果只是@property NSString*str; 则通过@synthesize自动生成的setter代码为:
C代码 收藏代码
-(void)setStr:(NSString*)value{
str=value;
}

如果是@property(retain)NSString*str; 则自动的setter内容为:
C代码 收藏代码
-(void)setStr:(NSString*)v{
if(v!=str){
[str release];
str=[v retain];
}
}

所有者属性
我们先来看看与所有权有关系的属性,关键字间的对应关系。

属性值 关键字 所有权
strong __strong 有
weak __weak 无
unsafe_unretained __unsafe_unretained 无
copy __strong 有
assign __unsafe_unretained 无
retain __strong 有
strong
该属性值对应 __strong 关键字,即该属性所声明的变量将成为对象的持有者。

weak
该属性对应 __weak 关键字,与 __weak 定义的变量一致,该属性所声明的变量将没有对象的所有权,并且当对象被破弃之后,对象将被自动赋值nil。

并且,delegate 和 Outlet 应该用 weak 属性来声明。同时,如上一回介绍的 iOS 5 之前的版本是没有 __weak 关键字的,所以 weak 属性是不能使用的。这种情况我们使用 unsafe_unretained。

unsafe_unretained
等效于__unsafe_unretaind关键字声明的变量;像上面说明的,iOS 5之前的系统用该属性代替 weak 来使用。

copy
与 strong 的区别是声明变量是拷贝对象的持有者。

assign
一般Scalar Varible用该属性声明,比如,int, BOOL。

retain
该属性与 strong 一致;只是可读性更强一些。

参考:
http://blog.eddie.com.tw/2010/12/08/property-and-synthesize/
http://www.cocoachina.com/bbs/read.php?tid=7322
http://www.cnblogs.com/pinping/archive/2011/08/03/2126150.html

声明的分类
在 Objective-C官方文档 中的Property一章里有对类Property详细说明。
@property中的声明列表已分类为以下几种:

1, 声明属性的访问方法:

getter=getterName
setter=setterName
声明访问属性的设置与获取方法名。
2,声明属性写操作权限:

readwrite
声明此属性为读写属性,即可以访问设置方法(setter),也可以访问获取方法(getter),与readonly互斥。
readonly
声明此属性为只读属性,只能访问此属性对应的获取方法(getter),与readwrite互斥。
3,声明写方法的实现:

assign
声明在setter方法中,采用直接赋值来实现设值操作。如:
C代码 收藏代码
-(void)setName:(NSString*)_name{
name = _name;
}

retain
声明在setter方法中,需要对设过来的值进行retain 加1操作。如:
C代码 收藏代码
-(void)setName:(NSString*)_name{
//首先判断是否与旧对象一致,如果不一致进行赋值。
//因为如果是一个对象的话,进行if内的代码会造成一个极端的情况:当此name的retain为1时,使此次的set操作让实例name提前释放,而达不到赋值目的。
if ( name != _name){
[name release];
name = [_name retain];
}
}

copy
调用此实例的copy方法,设置克隆后的对象。实现参考retain。
4,访问方法的原子性:

nonatomic
在默认的情况下,通过synthesized 实现的 setter与getter 都是原子性访问的。多线程同时访问时,保障访问方法同时只被访问一个线程访问,如:
C代码 收藏代码
[ _internal lock ]; // lock using an object-level lock
id result = [ [ value retain ] autorelease ];
[ _internal unlock ];
return result;

但如果设置nonatomic时,属性的访问为非原子性访问。

来源:http://wiki.magiche.net/pages/viewpage.action?pageId=1540101

@synthesize tabBarController=_tabBarController;
@synthesize 中可以定义 与变量名不相同的getter和setter的命名,籍此来保护变量不会被不恰当的访问

无法打开物理文件 XXX.mdf",操作系统错误 5:"5(拒绝访问。)"的解决办法

mikel阅读(640)

http://blog.csdn.net/blackfield/article/details/6550499

用T-SQL命令附加数据库时,出现如下异常信息:

无法打开物理文件 XXX.mdf”。操作系统错误 5:”5(拒绝访问。)”。 (Microsoft SQL Server,错误: 5120)

解决方案:

找到xxx.MDF与xxx_log.LDF文件,右键-属性-安全-在组或用户名处添加Authenticated Users-更改该组权限为完全权限,再次附加成功。

ASP.NET MVC搭建项目后台UI框架—4、tab多页签支持 - 邹琼俊 - 博客园

mikel阅读(1721)

来源: ASP.NET MVC搭建项目后台UI框架—4、tab多页签支持 – 邹琼俊 – 博客园

目录

  1. ASP.NET MVC搭建项目后台UI框架—1、后台主框架
  2. ASP.NET MVC搭建项目后台UI框架—2、菜单特效
  3. ASP.NET MVC搭建项目后台UI框架—3、面板折叠和展开
  4. ASP.NET MVC搭建项目后台UI框架—4、tab多页签支持
  5. ASP.NET MVC搭建项目后台UI框架—5、Demo演示Controller和View的交互

在点击左侧菜单中的选项时,我希望有Extjs、EasyUI等中类似的tab页签功能,因为这样可以支持多个页面的浏览,有时候我们可能需要同时 打开多个页面,如果不使用页签,那么每次要查看某个页面都要去重新调用并刷新,如果在网速慢或者该界面加载很耗时的情况下,简直会让人奔溃。因为我又不想 引入整个ExtJs等的内容。自然而然的,就想到了去网上找这种ui插件。找到了许多,不过我觉得CleverTabs比较适合我这个项目。效果如下:

Action

1、修改Right视图,添加如下js引用:

    <link href="~/Lib/CleverTabs/context/themes/base/jquery-ui.css" rel="stylesheet" />
    <script src="~/Scripts/jquery-1.8.3.min.js"></script>
    <script src="~/Lib/CleverTabs/scripts/jquery-ui.js"></script>
    <script src="~/Lib/CleverTabs/scripts/jquery.cleverTabs.js"></script>
    <script src="~/Lib/CleverTabs/scripts/jquery.contextMenu.js"></script>

2、添加js方法:

复制代码
   <script type="text/javascript">
           var tabs;
           $(function () {
               var h = $(document).height()-35;
               $("#tabs").height(h); //关于这里我要说明一下,如果不设置高度的话,它默认并不是发100%占满屏幕的,所以我这里使用了计算的方式,初始化界面高度
               tabs = $('#tabs').cleverTabs();
               $(window).bind('resize', function () {
                   tabs.resizePanelContainer();
               });

               tabs.add({
                   url: 'http://www.cnblogs.com/jiekzou/',
                   label: '我的博客',
                   //开启Tab后是否锁定(不允许关闭,默认: false)
                   lock: false
               });
               $('input[type="button"]').button();

           });
           function addTab(url,name) {
               tabs.add({
                   url: url,
                   label: name
               });
           }</script>
复制代码

3、修改Right视图中body主体:

复制代码
<body>
     <div class="sidebar fleft"><div class="btn" id="divFolding"></div></div>
    <div id="tabs" style="overflow:hidden; padding-top:0px; height:400px;">
        <ul>
        </ul>
    </div>
    </body>
复制代码

4、在Left视图中,添加如下js方法:Left中的菜单点击时调用Right视图中的添加页签方法addTab

        function goNewPage(url,name) {
            self.parent.frames["mainFrame"].addTab(url,name);
        }

修改Left视图中菜单的调用方法

<li><a target=”mainFrame” id=”channelManage” onclick=”goNewPage(‘/Channel/Index’,’渠道管理’);”>渠道管理</a></li& gt;

5、F5运行,你将看到如下效果:

框架中用到的js和css、Img:CssJsImg源码

博客地址: http://www.cnblogs.com/jiekzou/
博客版权: 本文以学习、研究和分享为主,欢迎转载,但必须在文章页面明显位置给出原文连接。
如果文中有不妥或者错误的地方还望高手的你指出,以免误人子弟。如果觉得本文对你有所帮助不如【推荐】一下!如果你有更好的建议,不如留言一起讨论,共同进步!
再次感谢您耐心的读完本篇文章。

等风来 还是人来风

mikel阅读(911)

互联网+让创业热潮风起云涌,争当台风口的猪,可多少是人来风,自我感觉良好?

微商火了,纷纷都做微商,一面是淘宝刷单的严惩,一边确实微商的风起,不知道又有几家爆发户,几家成了噱头。

互联网从来不缺概念的情况下,那些不明真相的群众都在被媒体引导着关注这个,关注那个,结果发现自己手里的钱倒是真的没多少了,干什么去了,总是在各种培训班和大会上真金白银的被忽悠走了,无利不起早的道理从来都是后知后觉,倒是成全了那些只说不做的大师们。

所以说互联网+是大形势,但是浑水摸鱼的人大有人在,在这种万民创业的大潮里面,要捂紧自己的口袋,别被忽悠才是硬道理。

java.io.FileNotFoundException的解决方法 - xybob的个人页面 - 开源中国社区

mikel阅读(1163)

来源: java.io.FileNotFoundException的解决方法 – xybob的个人页面 – 开源中国社区网上常见的一种方法:

<div class="container">
<div class="line number1 index0 alt2"><code class="java plain">URL url = </code><code class="java keyword">new</code> <code class="java plain">URL(urlstr);</code></div>
<div class="line number2 index1 alt1"><code class="java plain">HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();</code></div>
<div class="line number3 index2 alt2"><code class="java plain">httpCon.setRequestMethod(</code><code class="java string">"GET"</code><code class="java plain">);</code></div>
<div class="line number4 index3 alt1"><code class="java plain">httpCon.setDoOutput(</code><code class="java keyword">true</code><code class="java plain">);</code></div>
<div class="line number5 index4 alt2"><code class="java plain">httpCon.connect();</code></div>
<div class="line number5 index4 alt2">

原因:

4.0中设置httpCon.setDoOutput(true),将导致请求以post方式提交,即使设置了httpCon.setRequestMethod(“GET”);

将代码中的httpCon.setDoOutput(true);删除即可

我出现这个Exception时试了还是不行,结果是因为URL编码的问题。所以,对于凡是可能出现中文的参数值都用URLEncoder.encode(name, “UTF-8”)进行了URL编码,这才解决问题。

java发送post和get请求(1)---HttpURLConnection方式 - For The Future - 博客频道 - CSDN.NET

mikel阅读(1124)

来源: java发送post和get请求(1)—HttpURLConnection方式 – For The Future – 博客频道 – CSDN.NET


import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;

public class post_request {
public static final String GET_URL = "http://www.jiucool.com/request.php?key=j0r56u2";

public static final String POST_URL = "http://www.jiucool.com/request.php";
public static void readContentFromGet() throws IOException{
// 拼凑get请求的URL字串,使用URLEncoder.encode对特殊和不可见字符进行编码
String getURL = GET_URL + "&amp;activatecode=" + URLEncoder.encode("久酷博客", "utf-8");
URL getUrl = new URL(getURL);
// 根据拼凑的URL,打开连接,URL.openConnection函数会根据URL的类型,
// 返回不同的URLConnection子类的对象,这里URL是一个http,因此实际返回的是HttpURLConnection
HttpURLConnection connection = (HttpURLConnection) getUrl
.openConnection();
// 进行连接,但是实际上get request要在下一句的connection.getInputStream()函数中才会真正发到
// 服务器
connection.connect();
// 取得输入流,并使用Reader读取
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(),"utf-8"));//设置编码,否则中文乱码
System.out.println("=============================");
System.out.println("Contents of get request");
System.out.println("=============================");
String lines;
while ((lines = reader.readLine()) != null){
//lines = new String(lines.getBytes(), "utf-8");
System.out.println(lines);
}
reader.close();
// 断开连接
connection.disconnect();
System.out.println("=============================");
System.out.println("Contents of get request ends");
System.out.println("=============================");
}
public static void readContentFromPost() throws IOException{
// Post请求的url,与get不同的是不需要带参数
URL postUrl = new URL(POST_URL);
// 打开连接
HttpURLConnection connection = (HttpURLConnection) postUrl
.openConnection();
// Output to the connection. Default is
// false, set to true because post
// method must write something to the
// connection
// 设置是否向connection输出,因为这个是post请求,参数要放在
// http正文内,因此需要设为true
connection.setDoOutput(true);
// Read from the connection. Default is true.
connection.setDoInput(true);
// Set the post method. Default is GET
connection.setRequestMethod("POST");
// Post cannot use caches
// Post 请求不能使用缓存
connection.setUseCaches(false);
// This method takes effects to
// every instances of this class.
// URLConnection.setFollowRedirects是static函数,作用于所有的URLConnection对象。
// connection.setFollowRedirects(true);

// This methods only
// takes effacts to this
// instance.
// URLConnection.setInstanceFollowRedirects是成员函数,仅作用于当前函数
connection.setInstanceFollowRedirects(true);
// Set the content type to urlencoded,
// because we will write
// some URL-encoded content to the
// connection. Settings above must be set before connect!
// 配置本次连接的Content-type,配置为application/x-www-form-urlencoded的
// 意思是正文是urlencoded编码过的form参数,下面我们可以看到我们对正文内容使用URLEncoder.encode
// 进行编码
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
// 连接,从postUrl.openConnection()至此的配置必须要在connect之前完成,
// 要注意的是connection.getOutputStream会隐含的进行connect。
connection.connect();
DataOutputStream out = new DataOutputStream(connection
.getOutputStream());
// The URL-encoded contend
// 正文,正文内容其实跟get的URL中'?'后的参数字符串一致
String content = "" + "&amp;activatecode=" + URLEncoder.encode("久酷博客", "utf-8");
// DataOutputStream.writeBytes将字符串中的16位的unicode字符以8位的字符形式写道流里面
out.writeBytes(content);
out.flush();
out.close(); // flush and close
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(),"utf-8"));//设置编码,否则中文乱码
String line="";
System.out.println("=============================");
System.out.println("Contents of post request");
System.out.println("=============================");
while ((line = reader.readLine()) != null){
//line = new String(line.getBytes(), "utf-8");
System.out.println(line);
}
System.out.println("=============================");
System.out.println("Contents of post request ends");
System.out.println("=============================");
reader.close();
connection.disconnect();
}
}

HttpURLConnection.connect函数,实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。无论是post还是get,http请求实际上直到HttpURLConnection.getInputStream()这个函数里面

才正式发送出去。

在readContentFromPost() 中,顺序是重中之重,对connection对象的一切配置(那一堆set函数)都必须要在connect()函数执行之前完成。而对 outputStream的写操作,又必须要在inputStream的读

操作之前。这些顺序实际上是由http请求的格式决定的。

http 请求实际上由两部分组成,一个是http头,所有关于此次http请求的配置都在http头里面定义,一个是正文content,在connect()函数里面,会根据HttpURLConnection对象的配置值生成http头,

因此在调用connect函数之前,就必须把所有的配置准备好。

紧接着http头的是http请求的正文,正文的内容通过outputStream写入,实际上outputStream不是一个网络流,充其量是个字符串流,往里面写入的东西不会立即发送到网络,而是在流关闭后,根据输

入的内容生成http正文。

至此,http请求的东西已经准备就绪。在getInputStream()函数调用的时候,就会把准备好的http请求正式发送到服务器了,然后返回一个输入流,用于读取服务器对于此次http请求的返回信息。由于

http请求在getInputStream的时候已经发送出去了(包括http头和正文),因此在getInputStream()函数之后对connection对象进行设置(对http头的信息进行修改)或者写入 outputStream(对正文进

行修改)都是没有意义的了,执行这些操作会导致异常的发生。

iOS UI高级之网络编程(HTTP协议) - Running2Snail - 博客园

mikel阅读(989)

来源: iOS UI高级之网络编程(HTTP协议) – Running2Snail – 博客园

HTTP协议的概念

HTTP协议,Hyper Text Transfer Protocol (超文本传输协议)是用于从万维网服务器传送超文本到本地浏览器的传输协议,HTTP是一个应用层协议,由请求和响应构成,是一个标准的客户端服务器模型

 

了解C/S模式

Client(客户端)和Server(服务器)常常分别处在相距很远的两台计算 机上,Client程序的任务是将用户的要求提交给Server程序,再将Server程序返回的结果以特定的形式显示给用户;Server程序的任务是 接受客户程序提出的服务请求,进行相应的处理,再将结果返回给客户程序

 

iOS实现网络编程

 

HTTP协议请求如何实现

网络请求地址对象NSURL的作用及用法

网络请求对象NSURLRequest、NSMutableURLRequest的作用和用法

网络链接对象NSURLConnenction的作用及用法

网路链接协议NSURLConnectionDataDelegate的作用及用法

网络请求数据信息NSURLResponse的作用及用法

 

网络连接中所用到的类

我们将在后面的学习过程中遇到五个关于网络连接的类分别是:NSURL, NSURLRequest, NSMutableURLRequest, NSURLResponse, NSError.

NSURL:这个类封装了一个网络路径。

NSURLRequest:我们将通过这个类设置一些网络的请求信息。

NSMutableURLRequest:这个类是NSURLRequest的子类,可以设置一些请求参数

NSURLResponse:这个类可以接受一些从服务器返回的信息

NSError:这个类包含了我们在网络请求中遇到的错误信息

 

NSURL

url,统一资源定位符,也称为网址,因特网上标准的资源网址

一个典型的url:http://lily:123456@www.baidu.com/search?hl=en&source=hp&q=mySQL&aq=f&oq=&aqi=g10#page

url的符语法: 协议://授权/路径?查询              注释:url中网址后面的路径服务器中的文件夹 ?后面跟的是参数,多个参数时通过&(and)链接

协议:ftp://(文本传输协议) http://(超文本传输协议)

https://(安全超文本传输协议) file://(本地文件协议)

 

URL的请求方式

网络请求方式有两种:GET 和 POST

两种方式的相同点是:

都能给服务器传输数据

两种请求方式的不同点是:

1、给服务器传输数据的方式:

GCT:通过网址字符串

POST:通过data

2、传输数据的大小:

GET:网址字符串最多255字节

POST:使用NSData,容量超过1G

3、安全性:

GET:所有传输给服务器的数据,显示在网址里,类似于密码的明文输入,直接可见

POST:数据被转成NSData(二进制数据),类似于密码的密文输入,无法直接读取

 

连接方式

同步连接:程序容易出现卡死现象

异步链接:等待数据返回

异步链接有两种实现方式:

设置代理,接受数据

实现block

 

同步连接

同步连接请求可以让你能够从因特网请求数据,一旦发送同步请求后,程序将停止用户交互,直至服务器返回数据完成才可进行下一步操作。

 

首先我们建立一个TableViewController视图控制器在方法viewDidLoad里面我们将将网址字符串转成NSURL对象,然后根据NSURL对象创建NSURLRequest请求对象,然后建立同步链接,再通过jeson解析信息

 

异步连接

同步连接会让程序出现“卡死”现象,导致用户交互不友好,而异步链接正好改变了这一弊端,异步连接不会阻塞主线程,而会建立一个新的线程来操作,因此用户在发送出异步请求后依然可以对UI进行操作,程序可以继续进行。

 

异步连接(代理)

设置NSURLConnection代理

实现相应的代理方法:开始响应接受数据、接收数据 、成功、失败

 

 

 

创建了URL,指定代理之后,代理中的相应方法实现如下:

 

异步连接(block)

 

 

 

 

如何在ASP.NET MVC 中获取当前URL、controller、action - 天涯过者 - 博客园

mikel阅读(1085)

来源: 如何在ASP.NET MVC 中获取当前URL、controller、action – 天涯过者 – 博客园

一、URL的获取很简单,ASP.NET通用:
【1】获取 完整url (协议名+域名+虚拟目录名+文件名+参数)

string url=Request.Url.ToString();
【2】获取 虚拟目录名+页面名+参数:

string url=Request.RawUrl;
(或 string url=Request.Url.PathAndQuery;)

【3】获取 虚拟目录名+页面名:
string url=HttpContext.Current.Request.Url.AbsolutePath;
(或 string url= HttpContext.Current.Request.Path;)

【4】获取 域名:
string url=HttpContext.Current.Request.Url.Host;

【5】获取 参数:
string url= HttpContext.Current.Request.Url.Query;

【6】获取 端口:
Request.Url.Port

二、当前controller、action的获取
RouteData.Route.GetRouteData(this.HttpContext).Values[“controller”]
RouteData.Route.GetRouteData(this.HttpContext).Values[“action”]

MVC母版页RouteData.Values[“controller”]
MVC母版页RouteData.Values[“action”]
如果在视图中可以用
ViewContext.RouteData.Route.GetRouteData(this.Context).Values[“controller”]
ViewContext.RouteData.Route.GetRouteData(this.Context).Values[“action”]

ViewContext.RouteData.Values[“controller”]
ViewContext.RouteData.Values[“action”]

蛮王是种信仰,我会一直坚持下去

软件不做SaaS就是死

mikel阅读(1626)

过去的软件都是定制开发,软件开发商维护得是所有客户的不少版本和需求,结果投入的人力物力疲于奔命,最后年底算账大部分都内耗在了各种bug和修补上了。

版本多了,需求也就乱了,然后总得招人维护吧,结果这个版本一帮人,那个版本一帮人,哪个客户有新的需求,就得改,然后版本乱得没人弄的明白,一旦出现bug,就得满世界的版本更新。

世界就这么乱的!最后一大摊子就像个筛子,没人堵得上,最后压死骆驼的一根稻草就是版本太多人员再也无法修补上了。

SaaS的出现一下子让软件行业规则翻天覆地了,不再那么多版本需要维护,也不必那么多需求定制化更新,完全自助式的,想要就订购模块用上,不用了直接撤销模块即可。

定制需求也不怕,你就定制给他做,然后做成模板给他用,别人要是有类似的需求,那就也用上不就行了。

还是那七八个人,还是那两三杆枪,然后是后期的维护成本的直线下降,最后是规范化的版本管理和bug管理,不再需要劳心费力的应对不同功能定制的需求了。

但是万事开头难,如何架设上这个SaaS的架构是重中之重!没有好的架构,就没有灵活的定制开发和管理,这就显现出技术实力的核心竞争力的重要了。