如何让你的产品在冷启动之后快速获取用户?

大部分互联网产品在早期都会遇到两个问题:如何冷启动以及获得初始用户之后快速获得用户。上周硅谷投资机构、孵化器 500 Startups 旗下的 WMD.co 举办了一场以解决用户快速增长为主题的活动,多位来自成功互联网公司负责用户增长的高管分享了自己的经验之谈。

Andrew Johns 迄今为止的职业生涯大部分都是负责企业的用户增长,他曾经是 Facebook 用户增长团队的成员,后来在 Twitter 和 Quora 也负责过用户增长,现在是互联网金融企业 Wealthfront 负责用户的总监。

阅读全文 »

[ASP.NET MVC 小牛之路]12 - Section、Partial View 和 Child Action

概括的讲,View中的内容可以分为静态和动态两部分。静态内容一般是html元素,而动态内容指的是在应用程序运行的时候动态创建的内容。给View添加动态内容的方式可归纳为下面几种:

  • Inline code,小的代码片段,如 if 和 foreach 语句。
  • Html helper方法,用来生成单个或多个HTML元素,如view model、ViewBag等。
  • Section,在指定的位置插入创建好的一部分内容。
  • Partial view,存在于一个单独的视图文件中,作为子内容可在多个视图中共享。
  • Child action,相当于一个包含了业务逻辑的UI组件。当使用child action时,它调用 controller 中的 action 来返回一个view,并将结果插入到输出流中。

这个分类不是绝对的。前两种很简单,在前面的文章中也使用过。本文主要介绍后三种方式的应用。

本文目录

Section

Razor视图引擎支持将View中的一部分内容分离出来,以便在需要的地方重复利用,减少了代码的冗余。下面来演示如何使用Section。

创建一个MVC应用程序,选择基本模板。添加一个HomeController,编辑生成的Index方法如下:

	public ActionResult Index() {
    string[] names = { "Apple", "Orange", "Pear" };
    return View(names);
} 

右击Index方法,添加视图,编辑该视图如下:

复制代码
	@model string[] 
 
@{ 
    ViewBag.Title = "Index"; 
} 
 
@section Header { 
    <div class="view"> 
        @foreach (string str in new [] {"Home", "List", "Edit"}) { 
            @Html.ActionLink(str, str, null, new { style = "margin: 5px" })   
        } 
    </div> 
}

<div class="view"> 
    This is a list of fruit names: 
    @foreach (string name in Model) { 
        <span><b>@name</b></span> 
    } 
</div>

@section Footer { 
    <div class="view"> 
        This is the footer 
    </div> 
} 
复制代码

我们通过@section标签加section的名称来定义一个Section,这里创建了两个section:Header 和 Footer,习惯上一般把section放在View文件的开头或结尾以方便阅读。下面我们在 /Views/Shared/_Layout.cshtml 文件中来使用它们。

编辑 /Views/Shared/_Layout.cshtml 文件如下:

复制代码
	<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="utf-8" /> 
    <meta name="viewport" content="width=device-width" /> 
    <style type="text/css"> 
        div.layout { background-color: lightgray;} 
        div.view { border: thin solid black; margin: 10px 0;} 
    </style> 
    <title>@ViewBag.Title</title> 
</head> 
<body>
    @RenderSection("Header") 
 
    <div class="layout"> 
        This is part of the layout 
    </div> 
 
    @RenderBody() 
 
    <div class="layout"> 
        This is part of the layout 
    </div>

    @RenderSection("Footer")
<div class="layout"> 
        This is part of the layout 
    </div> 
</body> 
</html> 
复制代码

我们通过 @RenderSection 方法来调用section的内容,参数指定了section的名称。运行程序后可以看到如下结果:

阅读全文 »

[ASP.NET MVC 小牛之路]11 - Filter

Filter(筛选器)是基于AOP(面向方面编程)的设计,它的作用是对MVC框架处理客户端请求注入额外的逻辑,以非常简单优美的方式实现横切关注点(Cross-cutting Concerns)。横切关注点是指横越应该程序的多个甚至所有模块的功能,经典的横切关注点有日志记录、缓存处理、异常处理和权限验证等。本文将分别介绍MVC框架所支持的不同种类的Filter的创建和使用,以及如何控制它们的执行。

本文目录

四种基本 Filter 概述

MVC框架支持的Filter可以归为四类,每一类都可以对处理请求的不同时间点引入额外的逻辑处理。这四类Filter如下表:

在MVC框架调用acion之前,它会先判断有没有实现上表中的接口的特性,如果有,则在请求管道的适当的点调用特性中定义的方法。

MVC框架为这些种类的Filter接口实现了默认的特性类。如上表,ActionFilterAttribute 类实现了 IActionFilter 和 IResultFilter 两个接口,这个类是一个抽象类,必须对它提供实现。另外两个特性类,AuthorizeAttribute 和 HandleErrorAttribute, 已经提供了一些有用的方法,可以直接使用。

Filter 既能应用在单个的ation方法上,也能应用在整个controller上,并可以在acion和controller上应用多个Filter。如下所示:

复制代码
	[Authorize(Roles="trader")]  // 对所有action有效
public class ExampleController : Controller { 
 
    [ShowMessage]  // 对当前ation有效
    [OutputCache(Duration=60)] // 对当前ation有效
    public ActionResult Index() { 
        // ...  
    } 
}
复制代码

注意,对于自定义的controller的基类,应用于该基类的Filter也将对继承自该基类的所有子类有效。

阅读全文 »

[ASP.NET MVC 小牛之路]10 - Controller 和 Action (2)

继上一篇文章之后,本文将介绍 Controller 和 Action 的一些较高级特性,包括 Controller Factory、Action Invoker 和异步 Controller 等内容。

本文目录

开篇:示例准备

文章开始之前,我们先来了解一下一个请求的发出到Action方法处理后返回结果的流程,请试着理解下图:

本文的重点是 controller factory 和 action invoker。顾名思义,controller factory 的作用是创建为请求提供服务的Controller实例;action invoker 的作用是寻找并调用Action方法。MVC框架为这两者都提供了默认的实现,我们也可以对其进行自定义。

首先我们为本文要演示的示例做一些准备,把暂时想到的要用的 View、Controller 和 Action 都创建好。新建一个空的MVC应用程序,在Models文件夹中添加一个名为 Result 的Model,代码如下:

	namespace MvcApplication2.Models {
    public class Result {
        public string ControllerName { get; set; }
        public string ActionName { get; set; }
    }
}

在 /Views/Shared 文件夹下添加一个名为 Result.cshtml 的视图(不使用Layout),添加代码如下:

	...
<body>
    <div>Controller: @Model.ControllerName</div> 
    <div>Action: @Model.ActionName</div> 
</body>

本文的所有Action方法将都使用这同一个View,目的是显示被执行的Controller名称和Action名称。

然后我们创建一个名为Product的Controller,代码如下:

	public class ProductController : Controller {
        
    public ViewResult Index() {
        return View("Result", new Result {
            ControllerName = "Product",
            ActionName = "Index"
        });
    }

    public ViewResult List() {
        return View("Result", new Result {
            ControllerName = "Product",
            ActionName = "List"
        });
    }
}

阅读全文 »

你的头1000名用户怎么来?从笨的事情做起!

故事要从hotmail说起。1996年两个工程师想要自己出来单干,但是他们害怕自己的邮件被老板看到,于是做了一个基于网页的邮件系统,这就是hotmail的前身。结果这个业余时间做出来的产品马上得到了投资,但是真正推出市场的时候却反响平平。

那 时候大多公司宣传产品都是大手笔买大型广告牌和电台广告位。Hotmail没有用惯常手法,而是在每一封用hotmail发出的邮件最后,自动署名:“亲 爱的,你也可以和我一样用Hotmail的免费邮箱。” 这个现在看来挺平常的动作,在当时可是非常有创新意义的病毒式传播。

接 下来几天,hotmail用户以每天3,000人的速度爆发式增长,第一个100万用户在短短6个月内完成累积,第二个100万在随后的5个星期内实现。 当时的增长有多惊人呢?其中的一个小故事是,创始人Bhatia给他一个印度的朋友发了个邮件,3个星期以后印度市场就积累了30万用户。这个猛烈的增长 势头一直保持着,当1年半后出售给微软时,hotmail的用户数量达到了1200万,要知道,当时全球的网民数量才不过区区7千万。

从此以后,所有的创业公司说起产品的发布和用户的增长都会提到hotmail,希望能复制它的成功,仅仅用一个功能、一个战术、一个方法迅速引爆市场。大家都以为一个创业公司在早期要不就是迅速爆发,要不就是死掉。

但是,创业公司的失败都是相同的,创业公司的成功却是不可复制的。

Paul Graham蜀黍在YC孵化器里给创业者们最多的一个建议就是—— Do things don't scale. 在创业公司早期,你不可能等待用户们自己来,而是要主动地一个一个地赢得顾客。

阅读全文 »

C#调用java类、jar包方法

一、将已经编译后的java中Class文件进行打包;打包命令JAR

如:将某目录下的所有class文件夹全部进行打包处理;

使用的命令:jar cvf test.jar -C com/ .

其中test.jar为要生成的jar包;com/ . 为指定的当前目录下的文件夹,该文件夹包括子文件夹及class文件;

二、到IKVM官方网站下载IKVM需要的组件  http://www.ikvm.net/

  ikvm-0.42.0.3.zip

  ikvmbin-0.42.0.3.zip

  openjdk6-b16-stripped.zip

三、设置路径

解压ikvm-0.42.0.3.zip,并将%IKVM_HOME%/bin添加到path中。此处的%IKVM_HOME%是指解压后ikvm的主目录。

四、将java的jar包转换为.dll控件

使用的命令:ikvmc -out:IKVM.dll test.jar

其中IKVM.dll为将要生成的.dll控件文件名;test.jar为之前打包好的jar包文件。

五、在C#项目中添加所需的控件

  1、新建一个C#.NET项目,首先添加一下必须的DLLs

  %IKVM_HOME%/bin/IKVM.OpenJDK.Core.dll

  %IKVM_HOME%/bin/IKVM.Runtime.dll

  %IKVM_HOME%/bin/IKVM.Runtime.JNI.dll

  2、添加已生成的.dll文件

      将之前生成好的.dll文件加载到C#项目中

阅读全文 »

[ASP.NET MVC 小牛之路]09 - Controller 和 Action (1)

我们知道,在 MVC 中每个请求都会提交到 Controller 进行处理。Controller 是和请求密切相关的,它包含了对请求的逻辑处理,能对 Model 进行操作并选择 View 呈现给用户,对于业务和数据的逻辑代码以及接口和辅助类库等一般都不放到 Controller 中。

Controller 和 Action 的内容较多,我把它分成了两篇,也可能会分成三篇。本篇介绍 Controller 的实现、Controller 对状态数据的获取、ActionResult 和 Action 的数据传递,后续将介绍 Controller 工厂、Action Invoker 和暂时还没想好或正在学习的一些较高级的特性。

继承 IController 接口

在本系列前面的文章中,我们添加的 Controller 都是一个继承自抽象类 System.Web.Mvc.Controller 的普通类(请注意:controller(或Controller) 和 Controller 类在本文是两个意思,请在阅读本文时根据上下文理解)。Controller 抽象类封装了很多很实用的功能,让开发人员不用自己去写那些重复烦琐的处理代码。

如果不使用封装的 Controller 抽象类,我们也可以通过实现 IController 接口来创建自己的 controller。IController 接口中只有一个 Exctute 方法:

	public interface IController { 
    void Execute(RequestContext requestContext); 
}

IController 接口在 System.Web.Mvc 命名空间下,一个结构非常简单的接口。

当请求送到一个实现了 IController 接口的 controller 类时(路由系统通过请求的URL能够找到controller),Execute 方法被调用。

阅读全文 »

[ASP.NET MVC 小牛之路]08 - Area 使用

ASP.NET MVC允许使用 Area(区域)来组织Web应用程序,每个Area代表应用程序的不同功能模块。这对于大的工程非常有用,Area 使每个功能模块都有各自的文件夹,文件夹中有自己的Controller、View和Model,但对于管理也增加了一定的难度。

创建Area

 

右键工程选择 添加->区域,弹出如下填写Area的对话框:

点击添加后,工程目录结构如下:

和创建一个空MVC工程结构类似,Admin Area 有自己的 Controllers、Models 和 Views 文件夹,不一样的地方就是多了一个 AdminAreaRegistration.cs 文件,这个文件中定义了一个叫 AdminAreaRegistration 的类,它的内容如下:

	namespace MvcApplication1.Areas.Admin {
    public class AdminAreaRegistration : AreaRegistration {
        public override string AreaName {
            get {
                return "Admin";
            }
        }

        public override void RegisterArea(AreaRegistrationContext context) {
            context.MapRoute(
                "Admin_default",
                "Admin/{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional }
            );
        }
    }
}

系统自动生成的 AdminAreaRegistration 类继承至抽象类 AreaRegistration,并重写了 AreaName 属性和 RegisterArea 方法。在 RegisterArea 方法中它为我们定义了一个默认路由,我们也可在这个方法中定义专属于Admin Area的的其他路由。但有一点要注意,在这如果要给路由起名字,一定要确保它和整个应用程序不一样。

阅读全文 »

[ASP.NET MVC 小牛之路]07 - URL Routing

我们知道在ASP.NET Web Forms中,一个URL请求往往对应一个aspx页面,一个aspx页面就是一个物理文件,它包含对请求的处理。

而在ASP.NET MVC中,一个URL请求是由对应的一个Controller中的Action来处理的,由URL Routing来告诉MVC如何定位到正确的Controller和Action。

笼统的讲,URL Routing包含两个主要功能:解析URL 和 生成URL,本文将围绕这两个大点进行讲解。

URL Routing 的定义方式

让我们从下面这样一个简单的URL开始:

http://mysite.com/Admin/Index

在域名的后面,默认使用“/”来对URL进行分段。路由系统通过类似于 {controller}/{action} 格式的字符串可以知道这个URL的 Admin 和 Index 两个片段分别对应Controller和Action的名称。

默认情况下,路由格式中用“/”分隔的段数是和URL域名的后面的段数是一致的,比如,对于{controller}/{action} 格式只会匹配两个片段。如下表所示:

URL路由是在MVC工程中的App_Start文件夹下的RouteConfig.cs文件中的RegisterRoutes方法中定义的,下面是创建一个空MVC项目时系统生成的一个简单URL路由定义:

	public static void RegisterRoutes(RouteCollection routes) {
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

    routes.MapRoute( 
        name: "Default", 
        url: "{controller}/{action}/{id}", 
        defaults: new { controller = "Home", action = "Index",  id = UrlParameter.Optional } 
    );
}

静态方法RegisterRoutes是在Global.asax.cs文件中的Application_Start方法中被调用的,除了URL路由的定义外,还包含其他的一些MVC核心特性的定义:

	protected void Application_Start() { 
    AreaRegistration.RegisterAllAreas();

    WebApiConfig.Register(GlobalConfiguration.Configuration); 
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
    RouteConfig.RegisterRoutes(RouteTable.Routes); 
    BundleConfig.RegisterBundles(BundleTable.Bundles); 
}

RouteConfig.RegisterRoutes方法中传递的是 RouteTable 类的静态 Routes 属性,返回一个RouteCollection的实例。其实,“原始”的定义路由的方法可以这样写:

	public static void RegisterRoutes(RouteCollection routes) { 

    Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler()); 
    routes.Add("MyRoute", myRoute); 
}

创建Route对象时用了一个URL格式字符串和一个MvcRouteHandler对象作为构造函数的参数。不同的ASP.NET技术有不同的RouteHandler,MVC用的是MvcRouteHandler。

这种写法有点繁琐,一种更简单的定义方法是:

	public static void RegisterRoutes(RouteCollection routes) { 

    routes.MapRoute("MyRoute", "{controller}/{action}"); 
}

这种方法简洁易读,一般我们都会用这种方法定义路由。 

阅读全文 »

[ASP.NET MVC 小牛之路]06 - 使用 Entity Framework

在家闲着也是闲着,继续写我的[ASP.NET MVC 小牛之路]系列吧。在该系列的上一篇博文中,在显示书本信息列表的时候,我们是在程序代码中手工造的数据。本文将演示如何在ASP.NET MVC中使用Entity Framework从数据库中获取数据。虽然本文题目听上去比较简单,但如果你认真阅读,相信你一定会有所收获。

ORM 和 EF

当我们要开发一个应用程序,就要考虑怎样展示数据,怎样持久化数据。考虑这个问题时我们所要关心的东西,最重要的莫过于程序的性能、开发的简易性和代码的可维护、可扩展性。

持久化(Persistence),是指在应用程序中能永久地保存各个处理状态信息的机制。如果没有持久化这个机制,状态只能保存在内存中,机器关机后就会丢失。

在应用程序中,当要永久地保存数据时,我们会选择关系数据库(Relation DataBase);当要临时地保存数据时,我们则使用存储在内存中的对象。目前对于大多数开发人员来说,都是用关系数据库技术来作为持久化机制。虽然现在有些人正在尝试使用对象数据库(Object DataBase)技术,但关系数据库技术在许多年以内依然会是最主要的持久化机制。

为什么会出现对象数据库? SQL语言是一种非过程化的面向集合的解释型语言,而很多高级语言是过程化的面向对象的编译型语言,这使得两种语言之间存在着不匹配,导致效率不如人意。这种不匹配被称为“阻抗失配”,对象数据库的出现就是为了解决“阻抗失配”。

我们知道,在关系数据库技术中是用Table以行和列的结构来存放和组织数据的。在.NET 2.0以前,C#还没有泛型的时候,人们基本上用填充在DataSet中的DataTable来映射并存放从关系数据库中查询出来的数据,正如下面代码所示:

	using (SqlConnection conn = new SqlConnection(connString)) {
    using (SqlDataAdapter da = new SqlDataAdapter("Select * from order", conn)) {
        DataTable dt = new DataTable();
        da.Fill(dt);
        ...
    }
}

这种方式虽然能让面向对象语言匹配关系数据库,但它有一些明显的缺点,如非类型安全、难操控、低性能等。从.NET 2.0开始,人们开始通过泛型技术用实体模型对象的集合来匹配关系数据库中的数据,这种方式解决了DataTable方式所面临的缺点,且它有强类型、在VS中自动完成、编译时检查等特点,厂受.Net开发人员的喜爱。

为了让开发人员不用手动去做这种“匹配”工作,人们研发了很多ORM工具(如Entity Framework、NHibernate等)。ORM(Object Relation Mapping)工具,顾名思义,它的角色就是为了解决“关系”和“面向对象”之间的“失配”,它可以使得开发人员不用过多关心持久层而可以花更多的时间专注于业务。

Entity Framework(EF)是微软以ADO.NET为基础所发展出来的ORM解决方案,以Entity Data Model(EDM) 为主。EF利用了抽象化数据结构的方式,将每个数据库对象都转换成应用程序中的类对象(Entity),而数据字段都转换为属性 (Property),关系则转换为结合属性 (Association),让数据库的 E/R 模型完全的转成对象模型,如此让开发人员就能用熟悉的面向对象编程语言来调用访问。EF 4.0 以后支持Database FirstModel FirstCode First三种生成模式,Code First模式用的人比较多。

概念和理论性的东西就不多讲了,我也是带着疑问去查找网络资源根据自己的理解半摘半归纳出来的,而且鄙人不才,很多东西想描述但都不知道怎么组织语言。

本文目的主要是让读者对EF有个感性的认识,然后了解EF在ASP.NET MVC中的应用,不会去研究原理性的东西,下次有空再单独介绍EF吧。

阅读全文 »