2014年7月1日星期二

C#调用json.net执行json的相关操作


微信的access_token每次获取有效期为7200秒,也就是两个小时,在这两个小时内,再重复获取access_token不仅浪费带宽和速度,也增加了出错的几率,而且由于微信对于每日获取次数做了限制,所以每次操作都要获取一遍肯定不是一个好的办法,于是需要我们将获取到的access_token保存在本地,有效期内使用我们本地的数据。

由于我的场景是多用户,所以将AppId、Secret保存下来定时获取的方式肯定不合适。而由于没有太频繁的调用,所以我暂时选择使用json文件将用户的id、access_token、获取时间保存在本地json文件内,正好数据上也是键值对的组合,如果调用频繁那么可以试试键值对的数据库,比如redis之类的。

流程图:

【待加】

操作json我比较习惯使用json.net的库,即Newtonsoft.Json,引用之后便可以使用了。而json.net的网站文档还是非常简单不健全的,我搜了很多中文的个人博客,总觉得很混淆,概念理不清,直到我打开了stackoverflow上这个问题的页面,才终于理清了思路,之后再看官方文档就简单多了。

A JToken is a generic representation of a JSON value of any kind. It could be a string, object, array, property, etc.
A JProperty is a single JToken value paired with a name. It can only be added to a JObject, and its value cannot be another JProperty.
A JObject is a collection of JProperties. It cannot hold any other kind of JToken directly.

好了,以下是具体代码:

  • 没有文件,创建

  1. 函数System.AppDomain.CurrentDomain.BaseDirectory曾经突然抽了,得到的路径没有反斜杠,过了个周末又莫名其妙的好了,具体原因不明;
  2. File.Create(mem_access_token)后面一定要跟Close(),否则文件没有释放,其他进程无法操作
  3. 初始化Jobject对象不能用字符串"{}"转换,而是直接JObject AllAccToken = new JObject();
string access_token = "";
JObject AllAccToken = new JObject();

string mem_access_token = System.AppDomain.CurrentDomain.BaseDirectory + @"\Resource\js\MemAccessToken.json";
if(!File.Exists(mem_access_token))
{
    File.Create(mem_access_token).Close();
    using(StreamWriter sw = new StreamWriter(mem_access_token, false))
    {
        sw.Write(AllAccToken);
    }
}
  • 读取文件

using (FileStream fs = new FileStream(mem_access_token, FileMode.Open))
{
    using (StreamReader sr = new StreamReader(fs))
    {
        all_access_token = sr.ReadToEnd();
    }
}
  • 查询key

    如果存在,则查询对应的token是否已经过期,如果没过期则取值,否则调用微信接口获取并修改保存文件;如果不存在直接调用微信接口获取并添加保存文件
    调用的方法getAccessTokenFromWeiXin如果有access_token则返回access_token,否则返回errcode,因为errcode是5位,所以判断时长度写的6
if(AllAccToken[key] != null)
    {
        DateTime token_time = DateTime.Parse((string)AllAccToken.SelectToken(key).SelectToken("token_time"));
        //token未过期,读取
        if (token_time.AddSeconds(7200) > DateTime.Now)
        {
            return (string)AllAccToken.SelectToken(key).SelectToken("access_token");
        }
        //token已过期,重新获取并保存
        else
        {
            access_token = getAccessTokenFromWeiXin(Data);
            if ((access_token + "").Length > 6)
            {
                AllAccToken[key]["access_token"] = access_token;
                AllAccToken[key]["token_time"] = DateTime.Now;
                using (StreamWriter sw = new StreamWriter(mem_access_token, false))
                {
                    sw.Write(AllAccToken.ToString());
                }
            }
        }
    }
    //文件中没有token,获取并插入文件
else
    {
        access_token = getAccessTokenFromWeiXin(Data);
        if((access_token + "").Length > 6)
        {
            string new_access_token = @"{""access_token"":""" + access_token + @""",""token_time"":""" + DateTime.Now.ToString() + @"""}";
            AllAccToken.Add(memberPKId.ToString(), JToken.Parse(new_access_token));
            using (StreamWriter sw = new StreamWriter(mem_access_token, false))
            {
                sw.Write(AllAccToken.ToString());
            }
        }
    }

另外两个方法代码

调用微信接口获取access_token

public static string getAccessTokenFromWeiXin(ShpWeiXinShopAppData Data)
{
    Uri uri = new Uri(String.Format(@"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", Data.WxAppId_NULL, Data.WxSecret_NULL));
    HttpWebRequest wxReq = HttpWebRequest.Create(uri) as HttpWebRequest;
    string wxJson = "";
    using (HttpWebResponse wxTokenRes = wxReq.GetResponse() as HttpWebResponse)
    {
        StreamReader reader = new StreamReader(wxTokenRes.GetResponseStream());
        wxJson = reader.ReadToEnd();
    }
    JObject jo = JObject.Parse(wxJson);
    string access_token = jo["access_token"] == null ? (string)jo["errcode"] : (string)jo["access_token"];
    return access_token;
}

根据微信错误号获取微信错误信息

微信的所有返回码我也保存成了json文件,方便用户提示,而且这个文件可以做成只读的。

public static string WeiXinError(string key)
{
    using (FileStream fs = new FileStream(System.AppDomain.CurrentDomain.BaseDirectory + @"\Resource\XML\WeiXinErrcode.json", FileMode.Open))
    {
        using(StreamReader sr = new StreamReader(fs))
        {
            string error = sr.ReadToEnd();
            JObject wxErr = JObject.Parse(error);
            return wxErr[key].ToString();
        }
    }
}

小结

经过这次改进,程序优化不少,而且明确了改进方向;
json操作方法很多,找到自己习惯的就好,而这种键值对的方式其实还是很有用的,如果操作频繁的话可以考虑读入内存中操作、数据库中操作等方式。

%23%20C%23%u8C03%u7528json.net%u6267%u884Cjson%u7684%u76F8%u5173%u64CD%u4F5C%0A%0A@%28My%20Blogger%29%5BC%23%7Cjson%7Cjson.net%7C%u5FAE%u4FE1%7C%u6587%u4EF6%u64CD%u4F5C%5D%0A%0A%20%20%20%20%u5FAE%u4FE1%u7684access_token%u6BCF%u6B21%u83B7%u53D6%u6709%u6548%u671F%u4E3A7200%u79D2%uFF0C%u4E5F%u5C31%u662F%u4E24%u4E2A%u5C0F%u65F6%uFF0C%u5728%u8FD9%u4E24%u4E2A%u5C0F%u65F6%u5185%uFF0C%u518D%u91CD%u590D%u83B7%u53D6access_token%u4E0D%u4EC5%u6D6A%u8D39%u5E26%u5BBD%u548C%u901F%u5EA6%uFF0C%u4E5F%u589E%u52A0%u4E86%u51FA%u9519%u7684%u51E0%u7387%uFF0C%u800C%u4E14%u7531%u4E8E%u5FAE%u4FE1%u5BF9%u4E8E%u6BCF%u65E5%u83B7%u53D6%u6B21%u6570%u505A%u4E86%u9650%u5236%uFF0C%u6240%u4EE5%u6BCF%u6B21%u64CD%u4F5C%u90FD%u8981%u83B7%u53D6%u4E00%u904D%u80AF%u5B9A%u4E0D%u662F%u4E00%u4E2A%u597D%u7684%u529E%u6CD5%uFF0C%u4E8E%u662F%u9700%u8981%u6211%u4EEC%u5C06%u83B7%u53D6%u5230%u7684access_token%u4FDD%u5B58%u5728%u672C%u5730%uFF0C%u6709%u6548%u671F%u5185%u4F7F%u7528%u6211%u4EEC%u672C%u5730%u7684%u6570%u636E%u3002%0A---------------------%0A%0A%u7531%u4E8E%u6211%u7684%u573A%u666F%u662F%u591A%u7528%u6237%uFF0C%u6240%u4EE5%u5C06AppId%u3001Secret%u4FDD%u5B58%u4E0B%u6765%u5B9A%u65F6%u83B7%u53D6%u7684%u65B9%u5F0F%u80AF%u5B9A%u4E0D%u5408%u9002%u3002%u800C%u7531%u4E8E%u6CA1%u6709%u592A%u9891%u7E41%u7684%u8C03%u7528%uFF0C%u6240%u4EE5%u6211%u6682%u65F6%u9009%u62E9%u4F7F%u7528json%u6587%u4EF6%u5C06%u7528%u6237%u7684id%u3001access_token%u3001%u83B7%u53D6%u65F6%u95F4%u4FDD%u5B58%u5728%u672C%u5730json%u6587%u4EF6%u5185%uFF0C%u6B63%u597D%u6570%u636E%u4E0A%u4E5F%u662F%u952E%u503C%u5BF9%u7684%u7EC4%u5408%uFF0C%u5982%u679C%u8C03%u7528%u9891%u7E41%u90A3%u4E48%u53EF%u4EE5%u8BD5%u8BD5%u952E%u503C%u5BF9%u7684%u6570%u636E%u5E93%uFF0C%u6BD4%u5982redis%u4E4B%u7C7B%u7684%u3002%0A%23%23%23%23%u6D41%u7A0B%u56FE%uFF1A%0A%u3010%u5F85%u52A0%u3011%0A%0A%u64CD%u4F5Cjson%u6211%u6BD4%u8F83%u4E60%u60EF%u4F7F%u7528json.net%u7684%u5E93%uFF0C%u5373Newtonsoft.Json%uFF0C%u5F15%u7528%u4E4B%u540E%u4FBF%u53EF%u4EE5%u4F7F%u7528%u4E86%u3002%u800Cjson.net%u7684%u7F51%u7AD9%u6587%u6863%u8FD8%u662F%u975E%u5E38%u7B80%u5355%u4E0D%u5065%u5168%u7684%uFF0C%u6211%u641C%u4E86%u5F88%u591A%u4E2D%u6587%u7684%u4E2A%u4EBA%u535A%u5BA2%uFF0C%u603B%u89C9%u5F97%u5F88%u6DF7%u6DC6%uFF0C%u6982%u5FF5%u7406%u4E0D%u6E05%uFF0C%u76F4%u5230%u6211%u6253%u5F00%u4E86stackoverflow%u4E0A%5B%u8FD9%u4E2A%u95EE%u9898%u7684%u9875%u9762%5D%28http%3A//stackoverflow.com/questions/15413825/how-do-you-add-a-jtoken-to-an-jobject%29%uFF0C%u624D%u7EC8%u4E8E%u7406%u6E05%u4E86%u601D%u8DEF%uFF0C%u4E4B%u540E%u518D%u770B%u5B98%u65B9%u6587%u6863%u5C31%u7B80%u5355%u591A%u4E86%u3002%0A%0A%3EA%20JToken%20is%20a%20generic%20representation%20of%20a%20JSON%20value%20of%20any%20kind.%20It%20could%20be%20a%20string%2C%20object%2C%20array%2C%20property%2C%20etc.%0AA%20JProperty%20is%20a%20single%20JToken%20value%20paired%20with%20a%20name.%20It%20can%20only%20be%20added%20to%20a%20JObject%2C%20and%20its%20value%20cannot%20be%20another%20JProperty.%0AA%20JObject%20is%20a%20collection%20of%20JProperties.%20It%20cannot%20hold%20any%20other%20kind%20of%20JToken%20directly.%0A%0A%u597D%u4E86%uFF0C%u4EE5%u4E0B%u662F%u5177%u4F53%u4EE3%u7801%uFF1A%0A-%20%23%23%23%23%u6CA1%u6709%u6587%u4EF6%uFF0C%u521B%u5EFA%0A1.%20%u51FD%u6570%60System.AppDomain.CurrentDomain.BaseDirectory%60%u66FE%u7ECF%u7A81%u7136%u62BD%u4E86%uFF0C%u5F97%u5230%u7684%u8DEF%u5F84%u6CA1%u6709%u53CD%u659C%u6760%uFF0C%u8FC7%u4E86%u4E2A%u5468%u672B%u53C8%u83AB%u540D%u5176%u5999%u7684%u597D%u4E86%uFF0C%u5177%u4F53%u539F%u56E0%u4E0D%u660E%uFF1B%0A2.%20%60File.Create%28mem_access_token%29%60%u540E%u9762%u4E00%u5B9A%u8981%u8DDF%60Close%28%29%60%2C%u5426%u5219%u6587%u4EF6%u6CA1%u6709%u91CA%u653E%uFF0C%u5176%u4ED6%u8FDB%u7A0B%u65E0%u6CD5%u64CD%u4F5C%0A3.%20%u521D%u59CB%u5316Jobject%u5BF9%u8C61%u4E0D%u80FD%u7528%u5B57%u7B26%u4E32%22%7B%7D%22%u8F6C%u6362%uFF0C%u800C%u662F%u76F4%u63A5%60JObject%20AllAccToken%20%3D%20new%20JObject%28%29%3B%60%0A%0A%60%60%60%20C%23%0Astring%20access_token%20%3D%20%22%22%3B%0AJObject%20AllAccToken%20%3D%20new%20JObject%28%29%3B%0A%0Astring%20mem_access_token%20%3D%20System.AppDomain.CurrentDomain.BaseDirectory%20+%20@%22%5CResource%5Cjs%5CMemAccessToken.json%22%3B%0Aif%28%21File.Exists%28mem_access_token%29%29%0A%7B%0A%20%20%20%20File.Create%28mem_access_token%29.Close%28%29%3B%0A%20%20%20%20using%28StreamWriter%20sw%20%3D%20new%20StreamWriter%28mem_access_token%2C%20false%29%29%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20sw.Write%28AllAccToken%29%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A-%20%23%23%23%23%u8BFB%u53D6%u6587%u4EF6%0A%0A%60%60%60%20C%23%0Ausing%20%28FileStream%20fs%20%3D%20new%20FileStream%28mem_access_token%2C%20FileMode.Open%29%29%0A%7B%0A%20%20%20%20using%20%28StreamReader%20sr%20%3D%20new%20StreamReader%28fs%29%29%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20all_access_token%20%3D%20sr.ReadToEnd%28%29%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A-%20%23%23%23%23%u67E5%u8BE2key%0A%u5982%u679C%u5B58%u5728%uFF0C%u5219%u67E5%u8BE2%u5BF9%u5E94%u7684token%u662F%u5426%u5DF2%u7ECF%u8FC7%u671F%uFF0C%u5982%u679C%u6CA1%u8FC7%u671F%u5219%u53D6%u503C%uFF0C%u5426%u5219%u8C03%u7528%u5FAE%u4FE1%u63A5%u53E3%u83B7%u53D6%u5E76%u4FEE%u6539%u4FDD%u5B58%u6587%u4EF6%uFF1B%u5982%u679C%u4E0D%u5B58%u5728%u76F4%u63A5%u8C03%u7528%u5FAE%u4FE1%u63A5%u53E3%u83B7%u53D6%u5E76%u6DFB%u52A0%u4FDD%u5B58%u6587%u4EF6%0A%u8C03%u7528%u7684%u65B9%u6CD5%60getAccessTokenFromWeiXin%60%u5982%u679C%u6709access_token%u5219%u8FD4%u56DEaccess_token%uFF0C%u5426%u5219%u8FD4%u56DEerrcode%uFF0C%u56E0%u4E3Aerrcode%u662F5%u4F4D%uFF0C%u6240%u4EE5%u5224%u65AD%u65F6%u957F%u5EA6%u5199%u76846%0A%0A%60%60%60%20C%23%0Aif%28AllAccToken%5Bkey%5D%20%21%3D%20null%29%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20DateTime%20token_time%20%3D%20DateTime.Parse%28%28string%29AllAccToken.SelectToken%28key%29.SelectToken%28%22token_time%22%29%29%3B%0A%20%20%20%20%20%20%20%20//token%u672A%u8FC7%u671F%uFF0C%u8BFB%u53D6%0A%20%20%20%20%20%20%20%20if%20%28token_time.AddSeconds%287200%29%20%3E%20DateTime.Now%29%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%28string%29AllAccToken.SelectToken%28key%29.SelectToken%28%22access_token%22%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20//token%u5DF2%u8FC7%u671F%uFF0C%u91CD%u65B0%u83B7%u53D6%u5E76%u4FDD%u5B58%0A%20%20%20%20%20%20%20%20else%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20access_token%20%3D%20getAccessTokenFromWeiXin%28Data%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20%28%28access_token%20+%20%22%22%29.Length%20%3E%206%29%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20AllAccToken%5Bkey%5D%5B%22access_token%22%5D%20%3D%20access_token%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20AllAccToken%5Bkey%5D%5B%22token_time%22%5D%20%3D%20DateTime.Now%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20using%20%28StreamWriter%20sw%20%3D%20new%20StreamWriter%28mem_access_token%2C%20false%29%29%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sw.Write%28AllAccToken.ToString%28%29%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20//%u6587%u4EF6%u4E2D%u6CA1%u6709token%uFF0C%u83B7%u53D6%u5E76%u63D2%u5165%u6587%u4EF6%0Aelse%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20access_token%20%3D%20getAccessTokenFromWeiXin%28Data%29%3B%0A%20%20%20%20%20%20%20%20if%28%28access_token%20+%20%22%22%29.Length%20%3E%206%29%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20string%20new_access_token%20%3D%20@%22%7B%22%22access_token%22%22%3A%22%22%22%20+%20access_token%20+%20@%22%22%22%2C%22%22token_time%22%22%3A%22%22%22%20+%20DateTime.Now.ToString%28%29%20+%20@%22%22%22%7D%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20AllAccToken.Add%28memberPKId.ToString%28%29%2C%20JToken.Parse%28new_access_token%29%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20using%20%28StreamWriter%20sw%20%3D%20new%20StreamWriter%28mem_access_token%2C%20false%29%29%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sw.Write%28AllAccToken.ToString%28%29%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%60%60%60%0A%0A%u53E6%u5916%u4E24%u4E2A%u65B9%u6CD5%u4EE3%u7801%0A%23%23%23%23%u8C03%u7528%u5FAE%u4FE1%u63A5%u53E3%u83B7%u53D6access_token%0A%60%60%60%20C%23%0Apublic%20static%20string%20getAccessTokenFromWeiXin%28ShpWeiXinShopAppData%20Data%29%0A%7B%0A%20%20%20%20Uri%20uri%20%3D%20new%20Uri%28String.Format%28@%22https%3A//api.weixin.qq.com/cgi-bin/token%3Fgrant_type%3Dclient_credential%26appid%3D%7B0%7D%26secret%3D%7B1%7D%22%2C%20Data.WxAppId_NULL%2C%20Data.WxSecret_NULL%29%29%3B%0A%20%20%20%20HttpWebRequest%20wxReq%20%3D%20HttpWebRequest.Create%28uri%29%20as%20HttpWebRequest%3B%0A%20%20%20%20string%20wxJson%20%3D%20%22%22%3B%0A%20%20%20%20using%20%28HttpWebResponse%20wxTokenRes%20%3D%20wxReq.GetResponse%28%29%20as%20HttpWebResponse%29%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20StreamReader%20reader%20%3D%20new%20StreamReader%28wxTokenRes.GetResponseStream%28%29%29%3B%0A%20%20%20%20%20%20%20%20wxJson%20%3D%20reader.ReadToEnd%28%29%3B%0A%20%20%20%20%7D%0A%20%20%20%20JObject%20jo%20%3D%20JObject.Parse%28wxJson%29%3B%0A%20%20%20%20string%20access_token%20%3D%20jo%5B%22access_token%22%5D%20%3D%3D%20null%20%3F%20%28string%29jo%5B%22errcode%22%5D%20%3A%20%28string%29jo%5B%22access_token%22%5D%3B%0A%20%20%20%20return%20access_token%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%u6839%u636E%u5FAE%u4FE1%u9519%u8BEF%u53F7%u83B7%u53D6%u5FAE%u4FE1%u9519%u8BEF%u4FE1%u606F%0A%u5FAE%u4FE1%u7684%u6240%u6709%u8FD4%u56DE%u7801%u6211%u4E5F%u4FDD%u5B58%u6210%u4E86json%u6587%u4EF6%uFF0C%u65B9%u4FBF%u7528%u6237%u63D0%u793A%uFF0C%u800C%u4E14%u8FD9%u4E2A%u6587%u4EF6%u53EF%u4EE5%u505A%u6210%u53EA%u8BFB%u7684%u3002%0A%60%60%60%20C%23%0Apublic%20static%20string%20WeiXinError%28string%20key%29%0A%7B%0A%20%20%20%20using%20%28FileStream%20fs%20%3D%20new%20FileStream%28System.AppDomain.CurrentDomain.BaseDirectory%20+%20@%22%5CResource%5CXML%5CWeiXinErrcode.json%22%2C%20FileMode.Open%29%29%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20using%28StreamReader%20sr%20%3D%20new%20StreamReader%28fs%29%29%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20string%20error%20%3D%20sr.ReadToEnd%28%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20JObject%20wxErr%20%3D%20JObject.Parse%28error%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20wxErr%5Bkey%5D.ToString%28%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A--------------------------%0A%23%23%23%23%u5C0F%u7ED3%0A%u7ECF%u8FC7%u8FD9%u6B21%u6539%u8FDB%uFF0C%u7A0B%u5E8F%u4F18%u5316%u4E0D%u5C11%uFF0C%u800C%u4E14%u660E%u786E%u4E86%u6539%u8FDB%u65B9%u5411%uFF1B%0Ajson%u64CD%u4F5C%u65B9%u6CD5%u5F88%u591A%uFF0C%u627E%u5230%u81EA%u5DF1%u4E60%u60EF%u7684%u5C31%u597D%uFF0C%u800C%u8FD9%u79CD%u952E%u503C%u5BF9%u7684%u65B9%u5F0F%u5176%u5B9E%u8FD8%u662F%u5F88%u6709%u7528%u7684%uFF0C%u5982%u679C%u64CD%u4F5C%u9891%u7E41%u7684%u8BDD%u53EF%u4EE5%u8003%u8651%u8BFB%u5165%u5185%u5B58%u4E2D%u64CD%u4F5C%u3001%u6570%u636E%u5E93%u4E2D%u64CD%u4F5C%u7B49%u65B9%u5F0F%u3002

2014年6月24日星期二

C#微信开发之菜单管理


想进行微信公众平台开发已经有一年半了,之前也想过很多种可行性案例,可迟迟没有行动起来,昨天也看到了小区物业开启了微信服务,也是我思考的案例之一,也是我觉得最有用的一个案例,可苦于没有服务器资源没有进行,最近正好有一次机会开始了微信开发之旅,虽说有点晚,但总算也是涨点姿势。

今天进行的是微信自定义菜单,菜单功能包括以下4点:

进行微信开发需要认证的订阅号或服务号,并开启开发模式,具体方法不废话,直接说自定义菜单:

查询

很简单,就不说了。

修改

微信的接口中没有修改,所以要进行删除与创建两步操作。

  1. 获取access_token
    微信的每一步操作都是依靠这个token进行的,所以每步操作前都需要获取,有效期默认是7200秒,如果在这段时间内可以保存就不用再次获取
public static JObject access_token(int memberPKId)
{
    ShpWeiXinShopAppData wxData = new ShpWeiXinShopAppSystem().GetData(memberPKId);
    Uri uri = new Uri(String.Format(@"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", wxData.WxAppId_NULL, wxData.WxSecret_NULL));
    HttpWebRequest wxReq = HttpWebRequest.Create(uri) as HttpWebRequest;
    string wxJson = "";
    using (HttpWebResponse wxTokenRes = wxReq.GetResponse() as HttpWebResponse)
    {
        StreamReader reader = new StreamReader(wxTokenRes.GetResponseStream());
        wxJson = reader.ReadToEnd();
    }
    return JObject.Parse(wxJson);
}
  1. 删除菜单
JObject json = WeiXin.access_token(Int32.Parse(memberPKId));
if (json["access_token"] != null)
{
    string access_token = json["access_token"].ToString();
    Uri uri = new Uri(String.Format(@"https://api.weixin.qq.com/cgi-bin/menu/delete?access_token={0}", access_token));
    HttpWebRequest wxMenuReq = HttpWebRequest.Create(uri) as HttpWebRequest;
    using (HttpWebResponse wxDelMenuRes = wxMenuReq.GetResponse() as HttpWebResponse)
    {
        StreamReader reader = new StreamReader(wxDelMenuRes.GetResponseStream());
        menuDel = reader.ReadToEnd();
    }
    json = JObject.Parse(menuDel);
  1. 创建菜单
    创建时不仅需要传送参数,还需要传送一个json对象过去,先拼接成字符串再post,顺便吐槽一下,C#的post方法还没有jquery的post方便,怪不得那么多前端牛逼了
if(json["errcode"].ToString() == "0")
{
    DataTable dt = new ShpWeixinShopMenuSystem().GetShpWeixinShopMenuListByMemberPKId(Int32.Parse(memberPKId));
    DataRow[] firstMenu = dt.Select("MenuLevel = 1", "DisplayOrder");
    string menu = "{\"button\":[";

    foreach(DataRow dr1 in firstMenu)
    {
        menu += "{\"name\":\"" + dr1["MenuCaption"].ToString() + "\"";
        string expression = String.Format("MenuLevel = 2 and ParentMenu = {0}", dr1["MenuItemPKId"].ToString());
        DataRow[] secondMenu = dt.Select(expression, "DisplayOrder");
        if(secondMenu.Length > 0)
        {
            menu += ",\"sub_button\":[";
            foreach(DataRow dr2 in secondMenu)
            {
                menu += "{\"type\":\"view\",\"name\":\"" + dr2["MenuCaption"].ToString() + "\",\"url\":\"" + dr2["RelUrl"].ToString() + "\"},";
            }
            menu = menu.Remove(menu.Length-1, 1);
            menu += "]},";
        }
    }
    menu += "]}";

    HttpWebRequest wxMenuRequest = (HttpWebRequest)WebRequest.Create("https://api.weixin.qq.com/cgi-bin/menu/create?access_token=" + access_token);
    wxMenuRequest.ContentType = "text/json";
    wxMenuRequest.Method = "POST";

    using(StreamWriter sw = new StreamWriter(wxMenuRequest.GetRequestStream()))
    {
        sw.Write(menu);
        sw.Flush();
        sw.Close();
        HttpWebResponse wxMenuResponse = (HttpWebResponse)wxMenuRequest.GetResponse();
        using(StreamReader sr = new StreamReader(wxMenuResponse.GetResponseStream()))
        {
            menuCre = sr.ReadToEnd();
        }
    }
}

菜单事件推送

就是点击菜单按钮事件的通知。


写在最后

开发微信公众平台貌似不难,RESTapi调试起来也异常的方便,而且微信中没有太多的界面、用户体验之类的东西,所以整体来说开发速度比较快,难度不高,而真正需要的是想法与运营。

%23%20C%23%u5FAE%u4FE1%u5F00%u53D1%u4E4B%u83DC%u5355%u7BA1%u7406%0A%0A@%28My%20Blogger%29%5BC%23%7C.NET%7C%u5F00%u53D1%7C%u5FAE%u4FE1%7C%u5FAE%u4FE1%u516C%u4F17%u5E73%u53F0%5D%0A%0A%u60F3%u8FDB%u884C%u5FAE%u4FE1%u516C%u4F17%u5E73%u53F0%u5F00%u53D1%u5DF2%u7ECF%u6709%u4E00%u5E74%u534A%u4E86%uFF0C%u4E4B%u524D%u4E5F%u60F3%u8FC7%u5F88%u591A%u79CD%u53EF%u884C%u6027%u6848%u4F8B%uFF0C%u53EF%u8FDF%u8FDF%u6CA1%u6709%u884C%u52A8%u8D77%u6765%uFF0C%u6628%u5929%u4E5F%u770B%u5230%u4E86%u5C0F%u533A%u7269%u4E1A%u5F00%u542F%u4E86%u5FAE%u4FE1%u670D%u52A1%uFF0C%u4E5F%u662F%u6211%u601D%u8003%u7684%u6848%u4F8B%u4E4B%u4E00%uFF0C%u4E5F%u662F%u6211%u89C9%u5F97%u6700%u6709%u7528%u7684%u4E00%u4E2A%u6848%u4F8B%uFF0C%u53EF%u82E6%u4E8E%u6CA1%u6709%u670D%u52A1%u5668%u8D44%u6E90%u6CA1%u6709%u8FDB%u884C%uFF0C%u6700%u8FD1%u6B63%u597D%u6709%u4E00%u6B21%u673A%u4F1A%u5F00%u59CB%u4E86%u5FAE%u4FE1%u5F00%u53D1%u4E4B%u65C5%uFF0C%u867D%u8BF4%u6709%u70B9%u665A%uFF0C%u4F46%u603B%u7B97%u4E5F%u662F%u6DA8%u70B9%u59FF%u52BF%u3002%0A%0A%u4ECA%u5929%u8FDB%u884C%u7684%u662F%u5FAE%u4FE1%u81EA%u5B9A%u4E49%u83DC%u5355%uFF0C%u83DC%u5355%u529F%u80FD%u5305%u62EC%u4EE5%u4E0B4%u70B9%uFF1A%0A-%20**%5B%u521B%u5EFA%u83DC%u5355%5D%28http%3A//mp.weixin.qq.com/wiki/index.php%3Ftitle%3D%25E8%2587%25AA%25E5%25AE%259A%25E4%25B9%2589%25E8%258F%259C%25E5%258D%2595%25E5%2588%259B%25E5%25BB%25BA%25E6%258E%25A5%25E5%258F%25A3%29**%0A-%20**%5B%u67E5%u8BE2%u83DC%u5355%5D%28http%3A//mp.weixin.qq.com/wiki/index.php%3Ftitle%3D%25E8%2587%25AA%25E5%25AE%259A%25E4%25B9%2589%25E8%258F%259C%25E5%258D%2595%25E6%259F%25A5%25E8%25AF%25A2%25E6%258E%25A5%25E5%258F%25A3%29**%0A-%20**%5B%u5220%u9664%u83DC%u5355%5D%28http%3A//mp.weixin.qq.com/wiki/index.php%3Ftitle%3D%25E8%2587%25AA%25E5%25AE%259A%25E4%25B9%2589%25E8%258F%259C%25E5%258D%2595%25E5%2588%25A0%25E9%2599%25A4%25E6%258E%25A5%25E5%258F%25A3%29**%0A-%20**%5B%u83DC%u5355%u4E8B%u4EF6%u63A8%u9001%5D%28http%3A//mp.weixin.qq.com/wiki/index.php%3Ftitle%3D%25E8%2587%25AA%25E5%25AE%259A%25E4%25B9%2589%25E8%258F%259C%25E5%258D%2595%25E4%25BA%258B%25E4%25BB%25B6%25E6%258E%25A8%25E9%2580%2581%29**%0A%0A%u8FDB%u884C%u5FAE%u4FE1%u5F00%u53D1%u9700%u8981**%u8BA4%u8BC1%u7684%u8BA2%u9605%u53F7**%u6216**%u670D%u52A1%u53F7**%uFF0C%u5E76%u5F00%u542F%u5F00%u53D1%u6A21%u5F0F%uFF0C%u5177%u4F53%u65B9%u6CD5%u4E0D%u5E9F%u8BDD%uFF0C%u76F4%u63A5%u8BF4%u81EA%u5B9A%u4E49%u83DC%u5355%uFF1A%0A%0A%23%23%23%23%u67E5%u8BE2%0A%u5F88%u7B80%u5355%uFF0C%u5C31%u4E0D%u8BF4%u4E86%u3002%0A%0A%23%23%23%23%u4FEE%u6539%0A%u5FAE%u4FE1%u7684%u63A5%u53E3%u4E2D%u6CA1%u6709%u4FEE%u6539%uFF0C%u6240%u4EE5%u8981%u8FDB%u884C**%u5220%u9664**%u4E0E**%u521B%u5EFA**%u4E24%u6B65%u64CD%u4F5C%u3002%0A1.%20%u83B7%u53D6access_token%0A%u5FAE%u4FE1%u7684%u6BCF%u4E00%u6B65%u64CD%u4F5C%u90FD%u662F%u4F9D%u9760%u8FD9%u4E2Atoken%u8FDB%u884C%u7684%uFF0C%u6240%u4EE5%u6BCF%u6B65%u64CD%u4F5C%u524D%u90FD%u9700%u8981%u83B7%u53D6%uFF0C%u6709%u6548%u671F%u9ED8%u8BA4%u662F7200%u79D2%uFF0C%u5982%u679C%u5728%u8FD9%u6BB5%u65F6%u95F4%u5185%u53EF%u4EE5%u4FDD%u5B58%u5C31%u4E0D%u7528%u518D%u6B21%u83B7%u53D6%0A%0A%60%60%60%20C%23%0Apublic%20static%20JObject%20access_token%28int%20memberPKId%29%0A%7B%0A%20%20%20%20ShpWeiXinShopAppData%20wxData%20%3D%20new%20ShpWeiXinShopAppSystem%28%29.GetData%28memberPKId%29%3B%0A%20%20%20%20Uri%20uri%20%3D%20new%20Uri%28String.Format%28@%22https%3A//api.weixin.qq.com/cgi-bin/token%3Fgrant_type%3Dclient_credential%26appid%3D%7B0%7D%26secret%3D%7B1%7D%22%2C%20wxData.WxAppId_NULL%2C%20wxData.WxSecret_NULL%29%29%3B%0A%20%20%20%20HttpWebRequest%20wxReq%20%3D%20HttpWebRequest.Create%28uri%29%20as%20HttpWebRequest%3B%0A%20%20%20%20string%20wxJson%20%3D%20%22%22%3B%0A%20%20%20%20using%20%28HttpWebResponse%20wxTokenRes%20%3D%20wxReq.GetResponse%28%29%20as%20HttpWebResponse%29%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20StreamReader%20reader%20%3D%20new%20StreamReader%28wxTokenRes.GetResponseStream%28%29%29%3B%0A%20%20%20%20%20%20%20%20wxJson%20%3D%20reader.ReadToEnd%28%29%3B%0A%20%20%20%20%7D%0A%20%20%20%20return%20JObject.Parse%28wxJson%29%3B%0A%7D%0A%60%60%60%0A2.%20%u5220%u9664%u83DC%u5355%0A%0A%60%60%60%20C%23%0AJObject%20json%20%3D%20WeiXin.access_token%28Int32.Parse%28memberPKId%29%29%3B%0Aif%20%28json%5B%22access_token%22%5D%20%21%3D%20null%29%0A%7B%0A%20%20%20%20string%20access_token%20%3D%20json%5B%22access_token%22%5D.ToString%28%29%3B%0A%20%20%20%20Uri%20uri%20%3D%20new%20Uri%28String.Format%28@%22https%3A//api.weixin.qq.com/cgi-bin/menu/delete%3Faccess_token%3D%7B0%7D%22%2C%20access_token%29%29%3B%0A%20%20%20%20HttpWebRequest%20wxMenuReq%20%3D%20HttpWebRequest.Create%28uri%29%20as%20HttpWebRequest%3B%0A%20%20%20%20using%20%28HttpWebResponse%20wxDelMenuRes%20%3D%20wxMenuReq.GetResponse%28%29%20as%20HttpWebResponse%29%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20StreamReader%20reader%20%3D%20new%20StreamReader%28wxDelMenuRes.GetResponseStream%28%29%29%3B%0A%20%20%20%20%20%20%20%20menuDel%20%3D%20reader.ReadToEnd%28%29%3B%0A%20%20%20%20%7D%0A%20%20%20%20json%20%3D%20JObject.Parse%28menuDel%29%3B%0A%60%60%60%0A3.%20%u521B%u5EFA%u83DC%u5355%0A%u521B%u5EFA%u65F6%u4E0D%u4EC5%u9700%u8981%u4F20%u9001%u53C2%u6570%uFF0C%u8FD8%u9700%u8981%u4F20%u9001%u4E00%u4E2Ajson%u5BF9%u8C61%u8FC7%u53BB%uFF0C%u5148%u62FC%u63A5%u6210%u5B57%u7B26%u4E32%u518Dpost%uFF0C%u987A%u4FBF%u5410%u69FD%u4E00%u4E0B%uFF0CC%23%u7684post%u65B9%u6CD5%u8FD8%u6CA1%u6709jquery%u7684post%u65B9%u4FBF%uFF0C%u602A%u4E0D%u5F97%u90A3%u4E48%u591A%u524D%u7AEF%u725B%u903C%u4E86%0A%0A%60%60%60%20C%23%0Aif%28json%5B%22errcode%22%5D.ToString%28%29%20%3D%3D%20%220%22%29%0A%7B%0A%20%20%20%20DataTable%20dt%20%3D%20new%20ShpWeixinShopMenuSystem%28%29.GetShpWeixinShopMenuListByMemberPKId%28Int32.Parse%28memberPKId%29%29%3B%0A%20%20%20%20DataRow%5B%5D%20firstMenu%20%3D%20dt.Select%28%22MenuLevel%20%3D%201%22%2C%20%22DisplayOrder%22%29%3B%0A%20%20%20%20string%20menu%20%3D%20%22%7B%5C%22button%5C%22%3A%5B%22%3B%0A%20%20%20%20%0A%20%20%20%20foreach%28DataRow%20dr1%20in%20firstMenu%29%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20menu%20+%3D%20%22%7B%5C%22name%5C%22%3A%5C%22%22%20+%20dr1%5B%22MenuCaption%22%5D.ToString%28%29%20+%20%22%5C%22%22%3B%0A%20%20%20%20%20%20%20%20string%20expression%20%3D%20String.Format%28%22MenuLevel%20%3D%202%20and%20ParentMenu%20%3D%20%7B0%7D%22%2C%20dr1%5B%22MenuItemPKId%22%5D.ToString%28%29%29%3B%0A%20%20%20%20%20%20%20%20DataRow%5B%5D%20secondMenu%20%3D%20dt.Select%28expression%2C%20%22DisplayOrder%22%29%3B%0A%20%20%20%20%20%20%20%20if%28secondMenu.Length%20%3E%200%29%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20menu%20+%3D%20%22%2C%5C%22sub_button%5C%22%3A%5B%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20foreach%28DataRow%20dr2%20in%20secondMenu%29%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20menu%20+%3D%20%22%7B%5C%22type%5C%22%3A%5C%22view%5C%22%2C%5C%22name%5C%22%3A%5C%22%22%20+%20dr2%5B%22MenuCaption%22%5D.ToString%28%29%20+%20%22%5C%22%2C%5C%22url%5C%22%3A%5C%22%22%20+%20dr2%5B%22RelUrl%22%5D.ToString%28%29%20+%20%22%5C%22%7D%2C%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20menu%20%3D%20menu.Remove%28menu.Length-1%2C%201%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20menu%20+%3D%20%22%5D%7D%2C%22%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20menu%20+%3D%20%22%5D%7D%22%3B%0A%0A%20%20%20%20HttpWebRequest%20wxMenuRequest%20%3D%20%28HttpWebRequest%29WebRequest.Create%28%22https%3A//api.weixin.qq.com/cgi-bin/menu/create%3Faccess_token%3D%22%20+%20access_token%29%3B%0A%20%20%20%20wxMenuRequest.ContentType%20%3D%20%22text/json%22%3B%0A%20%20%20%20wxMenuRequest.Method%20%3D%20%22POST%22%3B%0A%20%20%20%20%0A%20%20%20%20using%28StreamWriter%20sw%20%3D%20new%20StreamWriter%28wxMenuRequest.GetRequestStream%28%29%29%29%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20sw.Write%28menu%29%3B%0A%20%20%20%20%20%20%20%20sw.Flush%28%29%3B%0A%20%20%20%20%20%20%20%20sw.Close%28%29%3B%0A%20%20%20%20%20%20%20%20HttpWebResponse%20wxMenuResponse%20%3D%20%28HttpWebResponse%29wxMenuRequest.GetResponse%28%29%3B%0A%20%20%20%20%20%20%20%20using%28StreamReader%20sr%20%3D%20new%20StreamReader%28wxMenuResponse.GetResponseStream%28%29%29%29%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20menuCre%20%3D%20sr.ReadToEnd%28%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%20%u83DC%u5355%u4E8B%u4EF6%u63A8%u9001%0A%u8FD9%u4E2A%u63A5%u53E3%u662F%u65B0%u52A0%u7684%uFF0C%u4E4B%u524D%u6CA1%u6709%u770B%u5230%uFF0C%u6682%u65F6%u6CA1%u6709%u7528%u5230%uFF0C%u5DF2%u52A0%u5165%u5F00%u53D1%u8BA1%u5212%uFF0C%u4EE5%u540E%u5199%u597D%u4E86%u518D%u6765%u66F4%u65B0%u3002%0A%0A----------------------------%0A%0A%23%23%23%23%u5199%u5728%u6700%u540E%0A%u5F00%u53D1%u5FAE%u4FE1%u516C%u4F17%u5E73%u53F0%u8C8C%u4F3C%u4E0D%u96BE%uFF0CRESTapi%u8C03%u8BD5%u8D77%u6765%u4E5F%u5F02%u5E38%u7684%u65B9%u4FBF%uFF0C%u800C%u4E14%u5FAE%u4FE1%u4E2D%u6CA1%u6709%u592A%u591A%u7684%u754C%u9762%u3001%u7528%u6237%u4F53%u9A8C%u4E4B%u7C7B%u7684%u4E1C%u897F%uFF0C%u6240%u4EE5%u6574%u4F53%u6765%u8BF4%u5F00%u53D1%u901F%u5EA6%u6BD4%u8F83%u5FEB%uFF0C%u96BE%u5EA6%u4E0D%u9AD8%uFF0C%u800C%u771F%u6B63%u9700%u8981%u7684%u662F%u60F3%u6CD5%u4E0E%u8FD0%u8425%u3002%0A%0A

2014年6月19日星期四

我为什么喜欢亚马逊


曾经有位做淘宝的朋友对我说:你为什么总是推崇亚马逊,我觉得在亚马逊上买东西比较low。我当时被气笑了,这也说明一个事实,任何国际高科技公司进入中国都有很强的壁垒,能做到被众人接受那更是难上加难。很多人都觉得亚马逊只是像京东一样的一家B2C的网站,却不知道其又是京东的抄袭对象,而距离,那只能呵呵了。
初次知道亚马逊还是网上看到有人说这是一家卖百货的网站,后来看到优秀logo设计案例中有亚马逊logo的详细解读,A-Z、笑脸、字体等都包含其中,再后来在同学家里看到了kindle,被精美的外表吸引,再后来看开发者论坛,知道了AWS,再后来亚马逊进入中国,日常购物+海淘没少在上面买东西,直到今天,亚马逊推出了第一款手机。

亚马逊的优势:

  • 贝佐斯:可以说没有贝佐斯就没有今天的亚马逊;
  • AWS:亚马逊云的技术含量甩出IT企业微软和苹果几条街;
  • 贴近生活:亚马逊销售百货,每个人需要;
  • 卓越的仓储物流系统:请注意,我使用的是卓越;
  • 强大的售后系统:如果你打过京东的售后就会由衷的赞叹亚马逊的专业;
  • 丰富的电子书资源:唯苹果可以匹敌;

kindle:

kindle已经经历了很多代产品,而且产品线也足够丰富,目前据说还准备开发一款超薄型kindle,由于对电子书比较喜欢,所以我也在paperwhite入华的第一天买了一部,还是挺喜欢的,只是即使有背光也无法在晚上躺在床上慢慢看,既伤眼睛也影响旁边人休息。
可是kindle已经构建出一个成熟的生态圈,拿现在时髦的话来说就是红海,资源丰富,硬件优秀,款式繁多,携带方便,总有一款适合你,不买也来看一看。网上很多人还是对n年前的kindle3、4情有独钟,足以见得亚马逊在设计上的独到。而电子书不仅大大的节省了空间,也不会丢失,只要使用账号就可以找到买过的所有书籍。

Fire Phone:

今天亚马逊推出了蓄谋已久的手机,名曰Fire Phone。看网上视频貌似做工还不错,不会像三棒子那样全身塑料。亮点功能有几点:
  • 3D技术:前面5个摄像头不是白装的,这也会带来前所未有的用户体验;
  • 无限的云:拍照可以直接存储至AWS,空间无限。在使用iphone时我的感慨就是,常用应用的空间其实16G基本够用,拍照和视频占用的空间特别大,亚马逊这样会逼的其他厂商降低云价格,好事;
  • 拍照扫货Firefly:对于一个购物网站来说,这种功能是必备无疑的了,重要的是信息量和识别准确率,希望国内也能足够好;
  • 与Fire TV的整合:我敢打赌国内那么多出盒子的没考虑到这个问题;
  • 操作系统:看视频有点黑莓的味道,不可否认黑莓真的很酷;
此外亚马逊海量的商品与电子书、电影资源也是其优势,缺点也有,就是裸机价格太高,有多少人愿意在同样价格的iphone6和安卓手机上选择后者呢。

关于抄袭

亚马逊在国内有不少的拥趸,不光是消费者,还有一大票厂商,只能说他们比较识货,现在AWS已经被抄的满天飞了,kindle也已经有太多的山寨货,都已经玩死一轮了,手机嘛,估计阿里、京东会迅速跟上,希望亚马逊且行且珍惜,早日入华早日调价。

亚马逊已经不仅仅是一个网站,而是一家IT界高科技公司,他的技术、用户体验都是业界的佼佼者,综合能力出其右者寥寥无几,而且贝佐斯曾经说过:不会为了董事会盈利而损害用户体验。我表示非常赞同,有这种做事的精神,叫人怎么能不喜欢这家公司。
%23%20%u6211%u4E3A%u4EC0%u4E48%u559C%u6B22%u4E9A%u9A6C%u900A%0A@%28My%20Blogger%29%5B%u4E9A%u9A6C%u900A%7Camazon%5D%0A%0A%u66FE%u7ECF%u6709%u4F4D%u505A%u6DD8%u5B9D%u7684%u670B%u53CB%u5BF9%u6211%u8BF4%uFF1A%u4F60%u4E3A%u4EC0%u4E48%u603B%u662F%u63A8%u5D07%u4E9A%u9A6C%u900A%uFF0C%u6211%u89C9%u5F97%u5728%u4E9A%u9A6C%u900A%u4E0A%u4E70%u4E1C%u897F%u6BD4%u8F83low%u3002%u6211%u5F53%u65F6%u88AB%u6C14%u7B11%u4E86%uFF0C%u8FD9%u4E5F%u8BF4%u660E%u4E00%u4E2A%u4E8B%u5B9E%uFF0C%u4EFB%u4F55%u56FD%u9645%u9AD8%u79D1%u6280%u516C%u53F8%u8FDB%u5165%u4E2D%u56FD%u90FD%u6709%u5F88%u5F3A%u7684%u58C1%u5792%uFF0C%u80FD%u505A%u5230%u88AB%u4F17%u4EBA%u63A5%u53D7%u90A3%u66F4%u662F%u96BE%u4E0A%u52A0%u96BE%u3002%u5F88%u591A%u4EBA%u90FD%u89C9%u5F97%u4E9A%u9A6C%u900A%u53EA%u662F%u50CF%u4EAC%u4E1C%u4E00%u6837%u7684%u4E00%u5BB6B2C%u7684%u7F51%u7AD9%uFF0C%u5374%u4E0D%u77E5%u9053%u5176%u53C8%u662F%u4EAC%u4E1C%u7684%u6284%u88AD%u5BF9%u8C61%uFF0C%u800C%u8DDD%u79BB%uFF0C%u90A3%u53EA%u80FD%u5475%u5475%u4E86%u3002%0A%0A%u521D%u6B21%u77E5%u9053%u4E9A%u9A6C%u900A%u8FD8%u662F%u7F51%u4E0A%u770B%u5230%u6709%u4EBA%u8BF4%u8FD9%u662F%u4E00%u5BB6%u5356%u767E%u8D27%u7684%u7F51%u7AD9%uFF0C%u540E%u6765%u770B%u5230%u4F18%u79C0logo%u8BBE%u8BA1%u6848%u4F8B%u4E2D%u6709%u4E9A%u9A6C%u900Alogo%u7684%u8BE6%u7EC6%u89E3%u8BFB%uFF0CA-Z%u3001%u7B11%u8138%u3001%u5B57%u4F53%u7B49%u90FD%u5305%u542B%u5176%u4E2D%uFF0C%u518D%u540E%u6765%u5728%u540C%u5B66%u5BB6%u91CC%u770B%u5230%u4E86kindle%uFF0C%u88AB%u7CBE%u7F8E%u7684%u5916%u8868%u5438%u5F15%uFF0C%u518D%u540E%u6765%u770B%u5F00%u53D1%u8005%u8BBA%u575B%uFF0C%u77E5%u9053%u4E86AWS%uFF0C%u518D%u540E%u6765%u4E9A%u9A6C%u900A%u8FDB%u5165%u4E2D%u56FD%uFF0C%u65E5%u5E38%u8D2D%u7269+%u6D77%u6DD8%u6CA1%u5C11%u5728%u4E0A%u9762%u4E70%u4E1C%u897F%uFF0C%u76F4%u5230%u4ECA%u5929%uFF0C%u4E9A%u9A6C%u900A%u63A8%u51FA%u4E86%u7B2C%u4E00%u6B3E%u624B%u673A%u3002%0A%0A%23%23%23%23%u4E9A%u9A6C%u900A%u7684%u4F18%u52BF%uFF1A%0A-%20**%u8D1D%u4F50%u65AF**%uFF1A%u53EF%u4EE5%u8BF4%u6CA1%u6709%u8D1D%u4F50%u65AF%u5C31%u6CA1%u6709%u4ECA%u5929%u7684%u4E9A%u9A6C%u900A%uFF1B%0A-%20**AWS**%uFF1A%u4E9A%u9A6C%u900A%u4E91%u7684%u6280%u672F%u542B%u91CF%u7529%u51FAIT%u4F01%u4E1A%u5FAE%u8F6F%u548C%u82F9%u679C%u51E0%u6761%u8857%uFF1B%0A-%20**%u8D34%u8FD1%u751F%u6D3B**%uFF1A%u4E9A%u9A6C%u900A%u9500%u552E%u767E%u8D27%uFF0C%u6BCF%u4E2A%u4EBA%u9700%u8981%uFF1B%0A-%20**%u5353%u8D8A%u7684%u4ED3%u50A8%u7269%u6D41%u7CFB%u7EDF**%uFF1A%u8BF7%u6CE8%u610F%uFF0C%u6211%u4F7F%u7528%u7684%u662F%u5353%u8D8A%uFF1B%0A-%20**%u5F3A%u5927%u7684%u552E%u540E%u7CFB%u7EDF**%uFF1A%u5982%u679C%u4F60%u6253%u8FC7%u4EAC%u4E1C%u7684%u552E%u540E%u5C31%u4F1A%u7531%u8877%u7684%u8D5E%u53F9%u4E9A%u9A6C%u900A%u7684%u4E13%u4E1A%uFF1B%0A-%20**%u4E30%u5BCC%u7684%u7535%u5B50%u4E66%u8D44%u6E90**%uFF1A%u552F%u82F9%u679C%u53EF%u4EE5%u5339%u654C%uFF1B%0A%0A%23%23%23%23kindle%uFF1A%0Akindle%u5DF2%u7ECF%u7ECF%u5386%u4E86%u5F88%u591A%u4EE3%u4EA7%u54C1%uFF0C%u800C%u4E14%u4EA7%u54C1%u7EBF%u4E5F%u8DB3%u591F%u4E30%u5BCC%uFF0C%u76EE%u524D%u636E%u8BF4%u8FD8%u51C6%u5907%u5F00%u53D1%u4E00%u6B3E%u8D85%u8584%u578Bkindle%uFF0C%u7531%u4E8E%u5BF9%u7535%u5B50%u4E66%u6BD4%u8F83%u559C%u6B22%uFF0C%u6240%u4EE5%u6211%u4E5F%u5728paperwhite%u5165%u534E%u7684%u7B2C%u4E00%u5929%u4E70%u4E86%u4E00%u90E8%uFF0C%u8FD8%u662F%u633A%u559C%u6B22%u7684%uFF0C%u53EA%u662F%u5373%u4F7F%u6709%u80CC%u5149%u4E5F%u65E0%u6CD5%u5728%u665A%u4E0A%u8EBA%u5728%u5E8A%u4E0A%u6162%u6162%u770B%uFF0C%u65E2%u4F24%u773C%u775B%u4E5F%u5F71%u54CD%u65C1%u8FB9%u4EBA%u4F11%u606F%u3002%0A%0A%u53EF%u662Fkindle%u5DF2%u7ECF%u6784%u5EFA%u51FA%u4E00%u4E2A%u6210%u719F%u7684%u751F%u6001%u5708%uFF0C%u62FF%u73B0%u5728%u65F6%u9AE6%u7684%u8BDD%u6765%u8BF4%u5C31%u662F%u7EA2%u6D77%uFF0C%u8D44%u6E90%u4E30%u5BCC%uFF0C%u786C%u4EF6%u4F18%u79C0%uFF0C%u6B3E%u5F0F%u7E41%u591A%uFF0C%u643A%u5E26%u65B9%u4FBF%uFF0C%u603B%u6709%u4E00%u6B3E%u9002%u5408%u4F60%uFF0C%u4E0D%u4E70%u4E5F%u6765%u770B%u4E00%u770B%u3002%u7F51%u4E0A%u5F88%u591A%u4EBA%u8FD8%u662F%u5BF9n%u5E74%u524D%u7684kindle3%u30014%u60C5%u6709%u72EC%u949F%uFF0C%u8DB3%u4EE5%u89C1%u5F97%u4E9A%u9A6C%u900A%u5728%u8BBE%u8BA1%u4E0A%u7684%u72EC%u5230%u3002%u800C%u7535%u5B50%u4E66%u4E0D%u4EC5%u5927%u5927%u7684%u8282%u7701%u4E86%u7A7A%u95F4%uFF0C%u4E5F%u4E0D%u4F1A%u4E22%u5931%uFF0C%u53EA%u8981%u4F7F%u7528%u8D26%u53F7%u5C31%u53EF%u4EE5%u627E%u5230%u4E70%u8FC7%u7684%u6240%u6709%u4E66%u7C4D%u3002%0A%0A%23%23%23%23Fire%20Phone%uFF1A%0A%u4ECA%u5929%u4E9A%u9A6C%u900A%u63A8%u51FA%u4E86%u84C4%u8C0B%u5DF2%u4E45%u7684%u624B%u673A%uFF0C%u540D%u66F0Fire%20Phone%u3002%u770B%u7F51%u4E0A%u89C6%u9891%u8C8C%u4F3C%u505A%u5DE5%u8FD8%u4E0D%u9519%uFF0C%u4E0D%u4F1A%u50CF%u4E09%u68D2%u5B50%u90A3%u6837%u5168%u8EAB%u5851%u6599%u3002%u4EAE%u70B9%u529F%u80FD%u6709%u51E0%u70B9%uFF1A%0A-%20**3D%u6280%u672F**%uFF1A%u524D%u97625%u4E2A%u6444%u50CF%u5934%u4E0D%u662F%u767D%u88C5%u7684%uFF0C%u8FD9%u4E5F%u4F1A%u5E26%u6765%u524D%u6240%u672A%u6709%u7684%u7528%u6237%u4F53%u9A8C%uFF1B%0A-%20**%u65E0%u9650%u7684%u4E91**%uFF1A%u62CD%u7167%u53EF%u4EE5%u76F4%u63A5%u5B58%u50A8%u81F3AWS%uFF0C%u7A7A%u95F4%u65E0%u9650%u3002%u5728%u4F7F%u7528iphone%u65F6%u6211%u7684%u611F%u6168%u5C31%u662F%uFF0C%u5E38%u7528%u5E94%u7528%u7684%u7A7A%u95F4%u5176%u5B9E16G%u57FA%u672C%u591F%u7528%uFF0C%u62CD%u7167%u548C%u89C6%u9891%u5360%u7528%u7684%u7A7A%u95F4%u7279%u522B%u5927%uFF0C%u4E9A%u9A6C%u900A%u8FD9%u6837%u4F1A%u903C%u7684%u5176%u4ED6%u5382%u5546%u964D%u4F4E%u4E91%u4EF7%u683C%uFF0C%u597D%u4E8B%uFF1B%0A-%20**%u62CD%u7167%u626B%u8D27Firefly**%uFF1A%u5BF9%u4E8E%u4E00%u4E2A%u8D2D%u7269%u7F51%u7AD9%u6765%u8BF4%uFF0C%u8FD9%u79CD%u529F%u80FD%u662F%u5FC5%u5907%u65E0%u7591%u7684%u4E86%uFF0C%u91CD%u8981%u7684%u662F%u4FE1%u606F%u91CF%u548C%u8BC6%u522B%u51C6%u786E%u7387%uFF0C%u5E0C%u671B%u56FD%u5185%u4E5F%u80FD%u8DB3%u591F%u597D%uFF1B%0A%0A%u7F3A%u70B9%u4E5F%u662F%u6709%u7684%uFF0C%u5C31%u662F%u88F8%u673A%u4EF7%u683C%u592A%u9AD8%uFF0C%u6709%u591A%u5C11%u4EBA%u613F%u610F%u5728%u540C%u6837%u4EF7%u683C%u7684iphone6%u548C%u5B89%u5353%u624B%u673A%u4E0A%u9009%u62E9%u540E%u8005%u5462%u3002%0A%0A%23%23%23%23%u5173%u4E8E%u6284%u88AD%0A%u4E9A%u9A6C%u900A%u5728%u56FD%u5185%u6709%u4E0D%u5C11%u7684%u62E5%u8DB8%uFF0C%u4E0D%u5149%u662F%u6D88%u8D39%u8005%uFF0C%u8FD8%u6709%u4E00%u5927%u7968%u5382%u5546%uFF0C%u53EA%u80FD%u8BF4%u4ED6%u4EEC%u6BD4%u8F83%u8BC6%u8D27%uFF0C%u73B0%u5728AWS%u5DF2%u7ECF%u88AB%u6284%u7684%u6EE1%u5929%u98DE%u4E86%uFF0Ckindle%u4E5F%u5DF2%u7ECF%u6709%u592A%u591A%u7684%u5C71%u5BE8%u8D27%uFF0C%u90FD%u5DF2%u7ECF%u73A9%u6B7B%u4E00%u8F6E%u4E86%uFF0C%u624B%u673A%u561B%uFF0C%u4F30%u8BA1%u963F%u91CC%u3001%u4EAC%u4E1C%u4F1A%u8FC5%u901F%u8DDF%u4E0A%uFF0C%u5E0C%u671B%u4E9A%u9A6C%u900A%u4E14%u884C%u4E14%u73CD%u60DC%uFF0C%u65E9%u65E5%u5165%u534E%u65E9%u65E5%u8C03%u4EF7%u3002%0A%0A--------------------%0A%0A%u4E9A%u9A6C%u900A%u5DF2%u7ECF%u4E0D%u4EC5%u4EC5%u662F%u4E00%u4E2A%u7F51%u7AD9%uFF0C%u800C%u662F%u4E00%u5BB6IT%u754C%u9AD8%u79D1%u6280%u516C%u53F8%uFF0C%u4ED6%u7684%u6280%u672F%u3001%u7528%u6237%u4F53%u9A8C%u90FD%u662F%u4E1A%u754C%u7684%u4F7C%u4F7C%u8005%uFF0C%u7EFC%u5408%u80FD%u529B%u51FA%u5176%u53F3%u8005%u5BE5%u5BE5%u65E0%u51E0%uFF0C%u800C%u4E14%u8D1D%u4F50%u65AF%u66FE%u7ECF%u8BF4%u8FC7%uFF1A%u4E0D%u4F1A%u4E3A%u4E86%u8463%u4E8B%u4F1A%u76C8%u5229%u800C%u635F%u5BB3%u7528%u6237%u4F53%u9A8C%u3002%u6211%u8868%u793A%u975E%u5E38%u8D5E%u540C%uFF0C%u6709%u8FD9%u79CD%u505A%u4E8B%u7684%u7CBE%u795E%uFF0C%u53EB%u4EBA%u600E%u4E48%u80FD%u4E0D%u559C%u6B22%u8FD9%u5BB6%u516C%u53F8%u3002

2014年6月17日星期二

关于文档格式Markdown的建议


关于文档格式Markdown的建议

关于Markdown

Markdown 是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档,然后转换成格式丰富的HTML页面。 —— 维基百科

目前程序员网站都已经开始支持甚至强制使用Markdown语法编写文档,比如evernote、github、stackoverflow等。在试用几次后,我强烈建议我们使用这种类型文档,因为:

  • 语法简洁:常用的就几种特殊字符,编辑熟练后无需使用鼠标
  • 排版优美:看到的是html的排版,再也不用看word里大量的回车符
  • 编辑器轻:基本都是在线编辑
  • 功能丰富:支持高亮代码段、公式、表格等等

Markdown文档编辑工具

名称 地址 优势
马克飞象 http://maxiang.info 可通过chrome下载到本地使用,同步evernote笔记
stackedit https://stackedit.io 功能强大,导出格式多,支持多个网盘及一键发布,内置图标
作业部落 https://www.zybuluo.com/mdeditor 多种编辑器模式,支持作业部落帐号,内置很多国内网站图标

另外github、stackoverflow都可以在线编辑,只是没有实时预览,且不是纯粹的文档编辑功能,如果单纯些文档不推荐使用;本地也可以使用一些文本编辑器,如sublime text,安装插件编辑Markdown,由于配置麻烦,也不推荐。

Markdown语法

由于Markdown实现的语法可以不同,所以每个编辑器的语法或多或少都有些差异,所以建议使用哪个编辑器可以查看对应的帮助文档(那里的文档都很漂亮)。


写在最后

希望这个推荐能够帮助大家提高工作效率,以后写文档、看文档时不再痛苦,技术发展的目的就是简化过程提供生产力的,我们不能让它白发展了。

%23%20%u5173%u4E8E%u6587%u6863%u683C%u5F0FMarkdown%u7684%u5EFA%u8BAE%0A%0A@%28%u5404%u79CD%u5B9E%u7528%u5DE5%u5177%29%5BMarkdown%7C%u6587%u6863%7C%u5DE5%u5177%5D%0A%0A%23%23%23%u5173%u4E8EMarkdown%0A%0A%3E%20Markdown%20%u662F%u4E00%u79CD%u8F7B%u91CF%u7EA7%u6807%u8BB0%u8BED%u8A00%uFF0C%u5B83%u5141%u8BB8%u4EBA%u4EEC%u4F7F%u7528%u6613%u8BFB%u6613%u5199%u7684%u7EAF%u6587%u672C%u683C%u5F0F%u7F16%u5199%u6587%u6863%uFF0C%u7136%u540E%u8F6C%u6362%u6210%u683C%u5F0F%u4E30%u5BCC%u7684HTML%u9875%u9762%u3002%20%20%20%20%u2014%u2014%20%5B%u7EF4%u57FA%u767E%u79D1%5D%28https%3A//zh.wikipedia.org/wiki/Markdown%29%0A%0A%u76EE%u524D%u7A0B%u5E8F%u5458%u7F51%u7AD9%u90FD%u5DF2%u7ECF%u5F00%u59CB%u652F%u6301%u751A%u81F3%u5F3A%u5236%u4F7F%u7528Markdown%u8BED%u6CD5%u7F16%u5199%u6587%u6863%uFF0C%u6BD4%u5982evernote%u3001github%u3001stackoverflow%u7B49%u3002%u5728%u8BD5%u7528%u51E0%u6B21%u540E%uFF0C%u6211%u5F3A%u70C8%u5EFA%u8BAE%u6211%u4EEC%u4F7F%u7528%u8FD9%u79CD%u7C7B%u578B%u6587%u6863%uFF0C%u56E0%u4E3A%uFF1A%0A-%20**%u8BED%u6CD5%u7B80%u6D01**%uFF1A%u5E38%u7528%u7684%u5C31%u51E0%u79CD%u7279%u6B8A%u5B57%u7B26%uFF0C%u7F16%u8F91%u719F%u7EC3%u540E%u65E0%u9700%u4F7F%u7528%u9F20%u6807%0A-%20**%u6392%u7248%u4F18%u7F8E**%uFF1A%u770B%u5230%u7684%u662Fhtml%u7684%u6392%u7248%uFF0C%u518D%u4E5F%u4E0D%u7528%u770Bword%u91CC%u5927%u91CF%u7684%u56DE%u8F66%u7B26%0A-%20**%u7F16%u8F91%u5668%u8F7B**%uFF1A%u57FA%u672C%u90FD%u662F%u5728%u7EBF%u7F16%u8F91%0A-%20**%u529F%u80FD%u4E30%u5BCC**%uFF1A%u652F%u6301%u9AD8%u4EAE%u4EE3%u7801%u6BB5%u3001%u516C%u5F0F%u3001%u8868%u683C%u7B49%u7B49%0A%0A%23%23%23Markdown%u6587%u6863%u7F16%u8F91%u5DE5%u5177%0A%7C%20%u540D%u79F0%20%20%20%20%20%20%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%u5730%u5740%20%7C%20%20%u4F18%u52BF%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%3A——–%20%7C%20——————%3A%7C%3A——————————————–%20%7C%0A%7C%60%u9A6C%u514B%u98DE%u8C61%60%20%7C%20http%3A//maxiang.info%20%7C%u53EF%u901A%u8FC7chrome%u4E0B%u8F7D%u5230%u672C%u5730%u4F7F%u7528%uFF0C%u540C%u6B65evernote%u7B14%u8BB0%20%7C%0A%7C%60stackedit%60%7C%20https%3A//stackedit.io%20%7C%u529F%u80FD%u5F3A%u5927%uFF0C%u5BFC%u51FA%u683C%u5F0F%u591A%uFF0C%u652F%u6301%u591A%u4E2A%u7F51%u76D8%u53CA%u4E00%u952E%u53D1%u5E03%uFF0C%u5185%u7F6E%u56FE%u6807%7C%0A%7C%60%u4F5C%u4E1A%u90E8%u843D%60%20%7C%20https%3A//www.zybuluo.com/mdeditor%20%7C%u591A%u79CD%u7F16%u8F91%u5668%u6A21%u5F0F%uFF0C%u652F%u6301%u4F5C%u4E1A%u90E8%u843D%u5E10%u53F7%uFF0C%u5185%u7F6E%u5F88%u591A%u56FD%u5185%u7F51%u7AD9%u56FE%u6807%7C%0A%0A%u53E6%u5916github%u3001stackoverflow%u90FD%u53EF%u4EE5%u5728%u7EBF%u7F16%u8F91%uFF0C%u53EA%u662F%u6CA1%u6709%u5B9E%u65F6%u9884%u89C8%uFF0C%u4E14%u4E0D%u662F%u7EAF%u7CB9%u7684%u6587%u6863%u7F16%u8F91%u529F%u80FD%uFF0C%u5982%u679C%u5355%u7EAF%u4E9B%u6587%u6863%u4E0D%u63A8%u8350%u4F7F%u7528%uFF1B%u672C%u5730%u4E5F%u53EF%u4EE5%u4F7F%u7528%u4E00%u4E9B%u6587%u672C%u7F16%u8F91%u5668%uFF0C%u5982sublime%20text%uFF0C%u5B89%u88C5%u63D2%u4EF6%u7F16%u8F91Markdown%uFF0C%u7531%u4E8E%u914D%u7F6E%u9EBB%u70E6%uFF0C%u4E5F%u4E0D%u63A8%u8350%u3002%0A%0A%23%23%23Markdown%u8BED%u6CD5%0A%u7531%u4E8EMarkdown%u5B9E%u73B0%u7684%u8BED%u6CD5%u53EF%u4EE5%u4E0D%u540C%uFF0C%u6240%u4EE5%u6BCF%u4E2A%u7F16%u8F91%u5668%u7684%u8BED%u6CD5%u6216%u591A%u6216%u5C11%u90FD%u6709%u4E9B%u5DEE%u5F02%uFF0C%u6240%u4EE5%u5EFA%u8BAE%u4F7F%u7528%u54EA%u4E2A%u7F16%u8F91%u5668%u53EF%u4EE5%u67E5%u770B%u5BF9%u5E94%u7684%u5E2E%u52A9%u6587%u6863%uFF08%u90A3%u91CC%u7684%u6587%u6863%u90FD%u5F88%u6F02%u4EAE%uFF09%u3002%0A%0A—————————%0A%23%23%23%23%u5199%u5728%u6700%u540E%0A%u5E0C%u671B%u8FD9%u4E2A%u63A8%u8350%u80FD%u591F%u5E2E%u52A9%u5927%u5BB6%u63D0%u9AD8%u5DE5%u4F5C%u6548%u7387%uFF0C%u4EE5%u540E%u5199%u6587%u6863%u3001%u770B%u6587%u6863%u65F6%u4E0D%u518D%u75DB%u82E6%uFF0C%u6280%u672F%u53D1%u5C55%u7684%u76EE%u7684%u5C31%u662F%u7B80%u5316%u8FC7%u7A0B%u63D0%u4F9B%u751F%u4EA7%u529B%u7684%uFF0C%u6211%u4EEC%u4E0D%u80FD%u8BA9%u5B83%u767D%u53D1%u5C55%u4E86%u3002

2014年6月13日星期五

使用C#对REST api的PUT调用

使用C#对REST api的PUT调用


最近需要添加一个REST的api接口,因为之前url都是丑陋的传参数格式,所以这次想试试目前比较网络比较流行的规范,就是同样的url利用访问方式的不同来执行查询、添加、修改、删除操作。

  • GET: 查询数据
  • POST:创建数据
  • PUT: 修改数据
  • DELETE:删除数据

首先是ashx文件部分:

switch (context.Request.RequestType)
{
    case "POST":
        result = CreateWeiXinPordService(context);
        break;
    case "PUT":
        result = ModifyWeiXinPordService(context);
        break;
    default:
        dt = GetWeiXinPordService(context);
        break;
}

由于是修改功能,底层接口都已经实现,于是通过判断请求类型来分别调用不同的接口。

其次是调用:

POST:

using(var client = new WebClient())
{
    var values = new NameValueCollection
    {
        { "memberPKId", "123"},
        { "beginDate", DateTime.Today.ToString()},
        { "endDate", DateTime.Today.ToString()},
        { "shopState", "1"},
        { "memoInfo", ""},
    };
    byte[] result = client.UploadValues("http://api.android.xxx.w/wx/ProdService.ashx", "POST", values);
    tb.Text = Encoding.ASCII.GetString(result);
}

PUT:

using (var client = new WebClient())
{
    var values = new NameValueCollection
    {
        { "servicePKId", "5"},
        { "endDate", this.Request["date"].ToString()},
        { "memoInfo", "修改啦"},
    };
    byte[] result = client.UploadValues("http://api.android.xxx.w/wx/ProdService.ashx", "PUT", values);
    tb2.Text = Encoding.ASCII.GetString(result);
}

在测试PUT方式时,页面报405错误,不允许使用该方法。原来IIS默认是不允许PUT动词的,求助了一下网络,这里再次说一下,stackoverflow是个好地方,唯一的缺点是无法注册,发现解决办法如下。

令IIS支持PUT访问方式的方法

  • 修改站点的web.config文件,添加以下内容
<system.webServer>
    <handlers>
      <remove name="WebDAV" />
      <remove name="SimpleHandlerFactory-Integrated-4.0" />
      <add name="SimpleHandlerFactory-Integrated-4.0" path="*.ashx" verb="*" type="System.Web.UI.SimpleHandlerFactory" resourceType="Unspecified" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
    <modules>
      <remove name="WebDAVModule" />
    </modules>
</system.webServer>

其中path可以指定文件,verb也可以指定几个访问方式,我这里是全部放开。

  • 修改访问文件的系统权限,添加iis_iuser用户组的修改权限

总结

到这里这个PUT的接口就可以顺利运行了,由于最近使用word发现排版非常不方便且不美观,于是自己试着用马克飞象写了这篇markdown格式的日志,感觉非常方便,就是代码块对C#的支持貌似不够好,但是也非常不错了,希望以后能引入工作中。

C#的路由程序还没研究明白,要不可以将url写的更优雅一点,留到下一次吧。

%23%u4F7F%u7528C%23%u5BF9REST%20api%u7684PUT%u8C03%u7528%0A@%28.net%29%5BC%23%7CREST%7CIIS%7CPUT%5D%0A%u6700%u8FD1%u9700%u8981%u6DFB%u52A0%u4E00%u4E2AREST%u7684api%u63A5%u53E3%uFF0C%u56E0%u4E3A%u4E4B%u524Durl%u90FD%u662F%u4E11%u964B%u7684%u4F20%u53C2%u6570%u683C%u5F0F%uFF0C%u6240%u4EE5%u8FD9%u6B21%u60F3%u8BD5%u8BD5%u76EE%u524D%u6BD4%u8F83%u7F51%u7EDC%u6BD4%u8F83%u6D41%u884C%u7684%u89C4%u8303%uFF0C%u5C31%u662F%u540C%u6837%u7684url%u5229%u7528%u8BBF%u95EE%u65B9%u5F0F%u7684%u4E0D%u540C%u6765%u6267%u884C%u67E5%u8BE2%u3001%u6DFB%u52A0%u3001%u4FEE%u6539%u3001%u5220%u9664%u64CD%u4F5C%u3002%0A-%20**GET**%uFF1A%20%u67E5%u8BE2%u6570%u636E%0A-%20**POST**%uFF1A%u521B%u5EFA%u6570%u636E%0A-%20**PUT**%uFF1A%20%u4FEE%u6539%u6570%u636E%0A-%20**DELETE**%uFF1A%u5220%u9664%u6570%u636E%0A%0A%23%23%23%23%u9996%u5148%u662Fashx%u6587%u4EF6%u90E8%u5206%uFF1A%0A%60%60%60%0Aswitch%20%28context.Request.RequestType%29%0A%7B%0A%20%20%20%20case%20%22POST%22%3A%0A%20%20%20%20%20%20%20%20result%20%3D%20CreateWeiXinPordService%28context%29%3B%0A%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20case%20%22PUT%22%3A%0A%20%20%20%20%20%20%20%20result%20%3D%20ModifyWeiXinPordService%28context%29%3B%0A%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20default%3A%0A%20%20%20%20%20%20%20%20dt%20%3D%20GetWeiXinPordService%28context%29%3B%0A%20%20%20%20%20%20%20%20break%3B%0A%7D%0A%60%60%60%0A%u7531%u4E8E%u662F%u4FEE%u6539%u529F%u80FD%uFF0C%u5E95%u5C42%u63A5%u53E3%u90FD%u5DF2%u7ECF%u5B9E%u73B0%uFF0C%u4E8E%u662F%u901A%u8FC7%u5224%u65AD%u8BF7%u6C42%u7C7B%u578B%u6765%u5206%u522B%u8C03%u7528%u4E0D%u540C%u7684%u63A5%u53E3%u3002%0A%0A%23%23%23%23%u5176%u6B21%u662F%u8C03%u7528%uFF1A%0A**POST%uFF1A**%0A%60%60%60C%23%0Ausing%28var%20client%20%3D%20new%20WebClient%28%29%29%0A%7B%0A%20%20%20%20var%20values%20%3D%20new%20NameValueCollection%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%7B%20%22memberPKId%22%2C%20%22123%22%7D%2C%0A%20%20%20%20%20%20%20%20%7B%20%22beginDate%22%2C%20DateTime.Today.ToString%28%29%7D%2C%0A%20%20%20%20%20%20%20%20%7B%20%22endDate%22%2C%20DateTime.Today.ToString%28%29%7D%2C%0A%20%20%20%20%20%20%20%20%7B%20%22shopState%22%2C%20%221%22%7D%2C%0A%20%20%20%20%20%20%20%20%7B%20%22memoInfo%22%2C%20%22%22%7D%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20byte%5B%5D%20result%20%3D%20client.UploadValues%28%22http%3A//api.android.xxx.w/wx/ProdService.ashx%22%2C%20%22POST%22%2C%20values%29%3B%0A%20%20%20%20tb.Text%20%3D%20Encoding.ASCII.GetString%28result%29%3B%0A%7D%0A%60%60%60%0A%0A**PUT%uFF1A**%0A%60%60%60C%23%0Ausing%20%28var%20client%20%3D%20new%20WebClient%28%29%29%0A%7B%0A%20%20%20%20var%20values%20%3D%20new%20NameValueCollection%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%7B%20%22servicePKId%22%2C%20%225%22%7D%2C%0A%20%20%20%20%20%20%20%20%7B%20%22endDate%22%2C%20this.Request%5B%22date%22%5D.ToString%28%29%7D%2C%0A%20%20%20%20%20%20%20%20%7B%20%22memoInfo%22%2C%20%22%u4FEE%u6539%u5566%22%7D%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20byte%5B%5D%20result%20%3D%20client.UploadValues%28%22http%3A//api.android.xxx.w/wx/ProdService.ashx%22%2C%20%22PUT%22%2C%20values%29%3B%0A%20%20%20%20tb2.Text%20%3D%20Encoding.ASCII.GetString%28result%29%3B%0A%7D%0A%60%60%60%0A%0A%u5728%u6D4B%u8BD5PUT%u65B9%u5F0F%u65F6%uFF0C%u9875%u9762%u62A5405%u9519%u8BEF%uFF0C%u4E0D%u5141%u8BB8%u4F7F%u7528%u8BE5%u65B9%u6CD5%u3002%u539F%u6765IIS%u9ED8%u8BA4%u662F%u4E0D%u5141%u8BB8PUT%u52A8%u8BCD%u7684%uFF0C%u6C42%u52A9%u4E86%u4E00%u4E0B%u7F51%u7EDC%uFF0C%u8FD9%u91CC%u518D%u6B21%u8BF4%u4E00%u4E0B%uFF0Cstackoverflow%u662F%u4E2A%u597D%u5730%u65B9%uFF0C%u552F%u4E00%u7684%u7F3A%u70B9%u662F%u65E0%u6CD5%u6CE8%u518C%uFF0C%u53D1%u73B0%u89E3%u51B3%u529E%u6CD5%u5982%u4E0B%u3002%0A%23%23%23%23%u4EE4IIS%u652F%u6301PUT%u8BBF%u95EE%u65B9%u5F0F%u7684%u65B9%u6CD5%0A-%20%u4FEE%u6539%u7AD9%u70B9%u7684web.config%u6587%u4EF6%uFF0C%u6DFB%u52A0%u4EE5%u4E0B%u5185%u5BB9%0A%0A%60%60%60XML%0A%3Csystem.webServer%3E%0A%20%20%20%20%3Chandlers%3E%0A%20%20%20%20%20%20%3Cremove%20name%3D%22WebDAV%22%20/%3E%0A%20%20%20%20%20%20%3Cremove%20name%3D%22SimpleHandlerFactory-Integrated-4.0%22%20/%3E%0A%20%20%20%20%20%20%3Cadd%20name%3D%22SimpleHandlerFactory-Integrated-4.0%22%20path%3D%22*.ashx%22%20verb%3D%22*%22%20type%3D%22System.Web.UI.SimpleHandlerFactory%22%20resourceType%3D%22Unspecified%22%20preCondition%3D%22integratedMode%2CruntimeVersionv4.0%22%20/%3E%0A%20%20%20%20%3C/handlers%3E%0A%20%20%20%20%3Cmodules%3E%0A%20%20%20%20%20%20%3Cremove%20name%3D%22WebDAVModule%22%20/%3E%0A%20%20%20%20%3C/modules%3E%0A%3C/system.webServer%3E%0A%60%60%60%0A%u5176%u4E2Dpath%u53EF%u4EE5%u6307%u5B9A%u6587%u4EF6%uFF0Cverb%u4E5F%u53EF%u4EE5%u6307%u5B9A%u51E0%u4E2A%u8BBF%u95EE%u65B9%u5F0F%uFF0C%u6211%u8FD9%u91CC%u662F%u5168%u90E8%u653E%u5F00%u3002%0A-%20%u4FEE%u6539%u8BBF%u95EE%u6587%u4EF6%u7684%u7CFB%u7EDF%u6743%u9650%uFF0C%u6DFB%u52A0iis_iuser%u7528%u6237%u7EC4%u7684%u4FEE%u6539%u6743%u9650%0A%0A-------------------------------%0A%23%23%23%23%u603B%u7ED3%0A%u5230%u8FD9%u91CC%u8FD9%u4E2APUT%u7684%u63A5%u53E3%u5C31%u53EF%u4EE5%u987A%u5229%u8FD0%u884C%u4E86%uFF0C%u7531%u4E8E%u6700%u8FD1%u4F7F%u7528word%u53D1%u73B0%u6392%u7248%u975E%u5E38%u4E0D%u65B9%u4FBF%u4E14%u4E0D%u7F8E%u89C2%uFF0C%u4E8E%u662F%u81EA%u5DF1%u8BD5%u7740%u7528%u9A6C%u514B%u98DE%u8C61%u5199%u4E86%u8FD9%u7BC7markdown%u683C%u5F0F%u7684%u65E5%u5FD7%uFF0C%u611F%u89C9%u975E%u5E38%u65B9%u4FBF%uFF0C%u5C31%u662F%u4EE3%u7801%u5757%u5BF9C%23%u7684%u652F%u6301%u8C8C%u4F3C%u4E0D%u591F%u597D%uFF0C%u4F46%u662F%u4E5F%u975E%u5E38%u4E0D%u9519%u4E86%uFF0C%u5E0C%u671B%u4EE5%u540E%u80FD%u5F15%u5165%u5DE5%u4F5C%u4E2D%u3002%0A%0AC%23%u7684%u8DEF%u7531%u7A0B%u5E8F%u8FD8%u6CA1%u7814%u7A76%u660E%u767D%uFF0C%u8981%u4E0D%u53EF%u4EE5%u5C06url%u5199%u7684%u66F4%u4F18%u96C5%u4E00%u70B9%uFF0C%u7559%u5230%u4E0B%u4E00%u6B21%u5427%u3002

2014年5月27日星期二

自己做的查询数据网页

距离页面哥离职也有两个月了,这两个月我被人事部的一个同事几乎每天骚扰,虽说是个美女,但是每天这么骚扰也显得咱技术太差了点,本着帮人同时也锻炼一下自己的原则,将这个查询数据的web页面重新改写了一遍,顺带着学习了一下一直想要学习的一些东西,比如html5、bootstrap、REST、json,另外还有局域网访问、Access数据库读取、Excel文件下载等技术点。

首先当然是查看原项目在原项目上修改,发现页面哥就是把东西往他们以前做项目的一个模板里面生套,从目录结构到没用的垃圾文件简直一塌糊涂,想修改根本没办法着手,而且那个页面界面太古老,不知道是哪年网上的模板,于是只能自己重新造轮子了。

首先将两个页面合并为一个页面,分为表单区和数据展示区,由于是.net开发,表单中按钮都使用了runat="server",但是没有用button,而是使用比较流行的a标签;日期选择框开始使用了html中input的date类型,但是发现只有chrome支持,于是换成bootstrap的datepicker插件,而且也给按钮换了样式并添加图标,下方的数据展示grid也适用bootstrap的样式,但是只用了悬停效果。

另外本来还有一个电话记录数据需要人事美女每天从电话系统中导出再在这里导入的,本着不能让美女(主要是用户)受累的原则,我想应该做成系统自动去获取数据,查看了电话记录系统,数据库是使用Access的,而且该系统没有开放api,统计功能点了没反应,备份功能形同虚设,而且系统使用时独占文件,无法读取该数据库,于是只好放大招,将两个电话系统的mdb文件拷贝到本地,再执行读取操作。另外sqlserver数据库统计工作是放在自动作业中定时操作,我将其更改为获取数据结束后执行统计,这样衔接更有效,而且前面的任务出错自然就不会执行统计操作了。

sqlserver中的统计代码也有修改,这就不讲了,轻车熟路。

再回到查询数据页面,有页面显示查询结果和导出到excel文件功能,获取数据直接读数据库太easy了,于是使用了目前比较流行的做法——前后端分离,后端使用ashx文件获取数据序列化后返回json,前端得到json后再反序列化得到datatable,使用.net自带的功能已经比较方便了,但是我还是使用了效率更高的json.net库,序列化与反序列化都只要两行代码就可以了,而且速度比自带的库要快的多。

最后导出到excel文件功能,网上一大堆例子,但是我还是遇到了问题,在chrome下文件名总是不对,而在其他浏览器下中文也都是乱码,后来发现是在文件名的地方使用了url.Encoding的方法,去掉直接使用字符串拼接的方式,一切都解决。附个图吧,其中导入文件功能已经不需要了:



附加一条,就是发布时使用了web deploy方式,这是我第一次使用,公司其他人私人有没有使用过我不清楚,但是公司的项目肯定是没有使用这种方式的,配置这个用了我半天时间,开始是使用web平台安装程序在线安装的deploy,死活连不成功,各种403、404错误,网上到处都找不到答案,今天单独下载了一个安装包,卸载重启重安装,神奇的好了,以后可以在内部推广一下,也可以减轻我的工作量。

总结一下:
1 stackoverflow是个好网站
2 程序中记录日志调试是个好办法,决定以后所有的项目都加记日志类
3 持续改进很重要,保持思考更重要
4 bootstrap算是入了门
5 能计算机做的尽量不要让人操作,降低出错几率而且提升效率

改进点:
1 图标在按钮中都偏上,之前的测试页面没有出现过
2 日期选择插件还不是中文,修改bootstrap.js文件后使用中文出现乱码
3 下方的数据展示grid还是.net控件,需要在一个runat="server"的form中使用,希望可以改为通用的grid
4 既然自动化,可以考虑不设界面,直接发邮件到指定人邮箱即可
5 设计上有待加强

2014年3月30日星期日

创业,需要创意

360的智键,小米的米键扎堆发布,首发一块钱,业界资讯小编们又一次集体高潮,啃口面包冲杯速溶,收起红包连夜赶稿,终于赶在8点20之前发了出来。

光发新闻稿不够过瘾,本着娱乐致死的精神,有人又跑去采访块按钮的创始人,想问问他们被捅了菊花是什么感受,这还用问吗,虽然专注捡肥皂20年,但是两个精装男一起上也让人受不了啊,不信你小编自己提臀试试。

如果就此同情快按钮那你还不如同情pressy,这个仅靠创意就在众筹网站上募集10万美金的小团队,看来注定打不进中国的市场了,因为硬件生产成本不可能比国内低,而销售量也不可能比国内大,毕竟玩起量来谁也干不过中国人,尤其大厂商那种办买半送的方式说不定会让这个键像随身wifi一样掀起一个小高潮。对了,众筹这个网站是中国的,pressy上的应该是kickstarter。看,什么都是抄来的。现在抄袭已经不光局限在软件,连硬件都开始,不信看看那一大票的智能手环和难看的手表吧。

国内创业公司风起云涌,平时随便在外国网上扒出一个点子就敢找金主谈融资。窃以为创业,如果你没有点先进的创意是没法跟大公司竞争的,剽窃来的创意也可以用,但是一定要加入自己的东西,并且后续也要有新想法才行,希望快按钮后续能将产品差异化,做好质量与服务,也能形成自己生态圈的闭环,在两大巨头面前这真的不容易。现在只有两家大公司跟进,如果百度腾讯这种抄袭大户也进入这个市场块按钮基本就没什么市场了。

2014年3月11日星期二

失散兄妹终得聚,疼迅断臂保江山

一贯擅长cosplay的腾讯昨日一改往日作风,将一年前高调运营的B2C后儿子易迅拱手送给京东,换来纯股份,刘强东春风得意请奶茶妹妹吃饭高调炒作,又引得互联网上一阵口水。

腾讯有钱后路线跟过去完全不同,以前是走别人的路让别人无路可走,起码有一个制作和运营的过程在那里,现在改成金融项目,学习梅耶尔的菜篮子工程,看到卖相好的直接拿下,华尔街记者刚批评完雅虎是创新杀手,当然这么说京东不合适,因为丫什么创新都没有,但是一个标榜互联网创新公司去玩金融的猫腻却有点令人鄙夷。

8年前发现易迅这个网站,觉得做的不错,专注攒机,在上面买的硬件送货快,价格低,态度好,售后强,所以这几年人家买配件我一直跟人推荐易迅,不过腾讯高调运营之后味道就有点变了,感觉越来越像京东。而京东我早就骂过,官方卖的东西里有假货,售后态度差什么都不懂,操着北京郊区口音净跟你说车轱辘话,打她们电话想骂娘,刘强定拙劣的炒作和忽悠手段更令人鄙视,这样一个行业垃圾服务商居然还成了易迅的标竿,把曾经纯洁的易迅拉下了马。

从用户体验来说,俩家越来越像,怎么看都像是一个娘胎里出来的亲兄妹,所以合并不失为一个好选择,京东少了一个最大的竞争对手,腾讯甩掉一个烧钱包袱,还能等着为期不远的上市升值,对消费者B2C又少了一个2B,都是好事。

最后我毫不负责任的推荐亚马逊,业界良心。

2014年2月12日星期三

两个半页面

    年前做了个在app中嵌入通讯录页面的任务,我自告奋勇设计UI Model,然后在项目没有明确产品经理的情况下恬不知耻的做了很多产品经理的事,没想到才两个半页面(有一个是隐藏的,点击显示出来也不是全屏),这么简单的一个任务前前后后会花费那么长时间。
    首先是大领导审核,领导级别高事情忙,光是审设计稿的时间就被拖了很多天,加上参照他意见的修改(页面简单,修改几乎花费时间很少),差不多过了一周。
    我心想审核通过了可以做了吧,结果页面同事说要等制作给页面,不然他处理不了兼容性问题,大哥,从最开始就让你研究各种效果了,你都干嘛去了,反正一周后这位老兄开始动工了,期间我的工作是设计另外一个任务的UI Model和改进通讯录地层代码(当然还有很多其他的工作),大概改了三个版本了,这位大哥干活时貌似把工作重点放在了找我bug上,虽然其中大部分都不是我的问题,但是那么多产品经理理论咱也不是白学的,一边改bug一边推进各位爷干活,不光陪笑脸还要耐心给他讲解sql知识,两个礼拜后页面总算做好了,由于有专人测试,我只是在浏览器上匆匆看了看忙完别的就回家过年了,昨天总算看到了新版app里的效果,错误太多
    1 css效果没有
    2 上下左右不对齐
    3 图标切的形状不对
    4 部门按钮打开后再点居然没关闭
    5 搜索框回车没反应
    6 电话号码属性不对
    7 电话图标效果不对
    8 详情页里没有的项目也展示了出来
    9 返回键不是返回到历史的上一页
    哥们你是玩我呢吗?这么垃圾的东西是怎呢上线的,如果我是产品经理一定要心痛至死,事实上我真的很心痛,就算你们对待工作不认真,但也不能这么明目张胆不按设计稿来啊,已经不指望你自己对页面有什么改进了,但是起码外表做出来看着得跟设计稿一样吧,这么做对得起跟你们一起做事的同事吗,对得起你每天坐的8小时吗。
    昨天跟app制作说了一下返回的问题,得到的是肯定的答覆,今天这边一个贱人来了句要学微信浏览网页一样在下面加后退和前进按钮,对了,突然想起来好像他才是兼任产品经理,我要真的是这个产品的产品经理我削死你你知道吗,在设计产品时候你干嘛去了,都上线了你说样子不对不合理,我们的对话是这样的我:
    我:你刚才说有什么问题?
    贱人:......(聊着qq)
    我:你刚才说什么问题啊?
    贱人:......(继续聊)
    我:你说有什么问题?(声音加大)
    贱人:(抬头看我一眼继续看屏幕)你那个点进去那么多层要返回那么多次不合理
    我:怎么不合理
    贱人:不合理
    我:哪不合理
    贱人:就是不合理
    我:你说app里操作点进去5层返回就要返5次这样不合理(事实上我们做的页面只有一层)?
    贱人:........就是不合理(然后不理我了)
    我说了几句看他没反应直接问你是不是要把产品往差了做,仍然没有回应。

    年前曾跟页面爷发过一次火,领导安慰人家说我小孩子脾气,那次也很难受,不管我是什么脾气,我那都是一心为了做好事情,每个人的工作态度难道您看不出来吗,其他的人不是在聊qq就是在看淘宝,只有我不停的学习不停的做事,凭什么那么说我。
    与贱人争论无果后我在qq群里发了句呵呵然后戴着耳机开始写blog。
    争论之前刚跟另外一个做页面的同事建议某网页前面要留白,操作成功通知不要用alert,换成ajax,不知道会不会接受我对我建议。
    最后再想点那个通讯录页面的改进点吧,改架构这种就不说了,除了那些错误要修改还有:
    1 页面图标全部换成字符型用css生成
    2 app采用缓存
    由于是纯浏览页面好像也没啥了,后面一个任务页面更多,我似乎看到了光明的未来在向我招手,这两天不断跟设计师讨论终于定下了设计稿,因为之前页面哥说特效做不出来,我这里把有效果的操作都去掉了,现在万分期待着这个平实的成果与兼任的口交称赞。
    对了,前面两个半页面一共用时26个工作日,最后的3天我没有参与。

2014年2月11日星期二

一个硬件构想-听歌利器

最近路上基本没有听广播,而是自己拷了一U盘的歌听,优点是没有广告和废话,纯净的听歌,音质比广播好;缺点是不会变,时间长了会听腻。
基于这个我想是否可以做一个类似mp3之类的产品,带wifi和蓝牙甚至插手机卡,使用手机客户端进行设置和升级,可以通过网络连接主流的一些听歌平台,比如国内的豆瓣电台、虾米、qq音乐、百度音乐、songtaste之类,甚至高端点连接国外的pandora等(原谅我国外知道的不多),再厉害点可以连接itunes store购买mp3下载下来听,硬件不能太大,要便于携带,可以使用插座或是usb供电(不是拖一根线的那种),机身上除了有一般mp3的按钮外,还要有收藏/喜欢按钮,要能推的动有源音箱,反正我家音箱插在iphone上声音小的可怜,平时出去可以当mp3听,在家或在车上可以当个流媒体的播放器。
不熟悉硬件,不知道这样一个东西实现起来难不难,在外面时流量是个问题,以前在V2上面看到一个人做过豆瓣电台的,好像最后没什么市场,东西也比较丑最后放弃了,希望我的这个设想能有用,要是有人联系我让我做那更好啦。

2014年2月6日星期四

活法2014

稻盛和夫有本成功学的书叫活法,里面主要是结合佛教的一些人生道理,既不是心灵鸡汤,也没有8什么小道消息,所以除了那些装逼的小企业家外基本没人爱看,而成功学的书没有一本不是骗子,我不是要说这个活法,而是自己身边的活法。
前两天回到老家,见了当地的老同学,听他们聊他们的生活,忽然感受到了每个人活法上的巨大不同。在老家,地方不大,其实平时靠步行基本都很方便,但是基本人人都买了车,房子更不用说,每个人都拼了命的买房,手里都不止一套,对于一个既不是一二级城市,又不是旅游胜地,更不算环境优秀的小地方来说,随着每年人口不断减少,居然能把房价从2000炒到5000+,我很佩服他们的勇气和魄力,当问到他们工资时,其实都不高,所以我估计每个人都或多或少有灰色收入,话题除了房子就是车,或是谁家小谁有了门路升了职,对于新鲜事物根本没有兴趣去了解,只有人民币才是真理,做公务员代表着出人头地,像极了我们以前眼中典型的中年人,他们连手中的手机都是今年刚换的智能机。
反过来看我这边,因为当初离开家的迫切想法来到了南方,辗转又到了魔都,起码也受到了大都市氛围的熏陶,几乎与他们截然相反。
前几天看到知乎上的一个人对比北上广和家乡二三线城市的对比,很有感触,在这里每个人都那么努力,每个人的生活也因为其他人的努力显得更加美好,城市就是因为这些努力的人才更有活力和竞争力。这次春节去大连,大连应该算是二线城市了,可城市里却缺少那些努力的人,出租车拒载成为常态,景点工作人员对顾客指手划脚,超市员工对顾客要求冷漠拒绝,机场地勤对于飞机晚点毫无歉意,反而责怪乘客,太多了。看到这些我反而暗自庆幸当初的决定,也会敦促我更加努力,这是我选择的活法。
新的一年,让我们生活的更加美好,加油。

2014年1月9日星期四

跟风骂骂12306

虽然我不需要为了春运在12306上抢票,但是之前看到逼哥转了个12306程序员一篇叫「其实我们一直在进步,只是你们假装看不到」的长微博,我就很好奇的去试用了一下。
首页依然没变,一直困扰我的难题还是为什么敲域名要跳转到子目录,那个私有密钥就不说了。到了订票页面,哇,果然大变样啊,比过去的界面好看的多,有点像web2.0刚红火那时的风格,换句话说,它跟现在其他优秀站点的外观有差不多10年的差距,试着用了用功能,我靠你还敢再卡点吗,连个控件打开都有卡顿,看了下源代码,大哥你们改掉的语句别让我们看到好吗,试着查询了一下,慢就一个字,我不能只说一次,刷票屡屡失败,让我想起了第一次上网开一个页面等了半小时的情景,也许性能上的差距更大。
12306的程序员大哥们,就像你长微博里说的,你们有先出招的优势,但是你们没有技术,这话说的真tmd对,但是你理直气壮的说就是你的不对了,你们不能自己闭门造轮子啊,这么高并发是换谁也扛不住,但是你们的瓶颈在性能,不是页面布局啊,阿里现在处理并发有一套,可以向他们取取经啊,直接砸钱挖人也好。你们现在和阿里的差距就像是清政府和八国联军,不加大投入向人家学习差距只能越来越大啊,你们努力有个毛用,谁不努力啊,你得比别人快才行。
上个月正好回了趟大学,发现现在的宿舍条件已经像我10多年前想要的样子了,其实没多难,无非就是双层玻璃不漏风,不限电,有空调,最好有热水器,对于一个初到南方的北方人来说,这些要求很奢侈吗,夏天生痱子冬天生冻疮,逢年过节发两块长毛月饼,你们这是育人还是毁人,如果校长能在破宿舍里住两天他肯定早就给换了。小米他们学校的校长经常跟学生一起吃食堂,处理学生意见,学生跟校外产生冲突后保护学生,我们校长只会给学生开除,买回全市市面上报道学校反面新闻的报纸,就算你现在已经条件提高了,可是你已经晚了10年,跟12306一样,还自己闭门造轮子只会越来越落后。

2014年1月7日星期二

让互联网思维见鬼去吧

最近随便打开一个IT类网站,十篇文章里必定2-4篇有互联网思维、2-4篇大数据,1-2篇BAT,真正干货只占十分之一不到,原来IT小编这么好当啊,整的像新闻联播一样都让人摸到规律了,连体育编辑还会写点色情小说呢,你们还好意思整天发文章吗。
这帮傻逼们今天要用互联网思维做手机,明天要用互联网思维造汽车,后天要用互联网思维做销售,大后天用互联网思维做马桶,我真想把马桶扣你们丫头上洗洗你们浆糊脑袋,以后别张嘴闭嘴互联网。
宽带和智能手机的普及带来的这波大潮让这帮孙子们集体亢奋,现在随便出个点子拉十几个人七八条枪就敢说要革了传统互联网的命,拉这个老板,找那个风投,都以为自己是乔布斯转世呢,平时没事给人家写写软文捞点外快。但别忘了能到今天那是运营商和乔老爷们的功劳,真正改变生活的是他们,而不是什么狗屁互联网思维,不信你到下边问问乔老爷知不知道什么是互联网思维。产品、流程、品质的进步大部分源自于人们对美的追求,有没有互联网都一个鸟样,没听说哪个球员苦练绝技是受了互联网的启发的。当然每个人对美的具体概念不同,这才显出审美和能力的差距。
都说互联网烧钱,你知道哪个行业不烧钱吗,这年头还有一本万利的买卖吗,如果有请一个告诉我,我代表我全家感谢你。别看现在富豪榜里有丁三石小马哥霍金马李红眼这些搞IT的,他们那都是股价撑着呢,真正的实业比不上任何一个做房地产的,你看IT公司赚钱多,能进500强吗,看看中国进了500强的都是什么公司,要赚钱还得靠垄断,还有那闷声发大财的主儿,比如现在儿女风光无限的前领导人一家子,改变人们生活方式的不止是IT,上边发个文件,你就白干一年,人家多印点纸,你就苦不堪言,大佬吃个包子,你就得琢磨半天,大户哗哗数钱,你就光杆过年,所以别再扯犊子了,发点干货好吗,也让我过个好年。

2014年1月1日星期三

勾3搭4

马上跨年,马上睡觉
总结一下吧,2013除了银子收获还是不小,除了德什么都缺,这么大年纪了,早年的锐利早已磨圆,换个说法就是更能理解他人了,所幸还保留着一点人性和追求,而且整个一年能够持续不断的进步。
1 找到了喜欢的锻炼项目-羽毛球
2 看了不少书,还有更多网络上的知识
3 已经很少上和谐站点了,身心得到净化
4 技术上进步最大
对于14年,有几个展望:
1 希望物质水平大幅度提高
2 希望小米能够找到喜欢的工作
3 希望丁丁喜欢上幼儿园
4 希望自己成为"堆栈"型人才

2013年12月5日星期四

如果我们这样做硬件

手机中有一项特别牛逼的功能,虽然极少被使用,但是必须承认这个功能的牛逼之处,就是恢复出厂设置功能,就连很久很久以前的功能机上都必不可少,手机为了保证可以使用,花费一定内存保存这些默认数据,使手机不至于因为一个NULL值而惨遭抛弃,如果我们生活中的硬件也能这样呢?

不敢想,那样就实在太牛逼了,就像发生了时光倒流一样难以置信。

当然这样的难度非常大,好吧,那我们把要求降低一点,如果我们的硬件中能够使用电脑板控制的,比如电器,在硬件没有损坏的情况下能够将系统恢复成出厂设置,这样厂家的售后可以减轻一半的工作量,因为很多问题其实都是他们的bug造成的,而售后却从来不承认,只是告诉你硬件坏了,更换就可以,一片800,两片优惠1500,您换几片,这也属于王八蛋态度的范畴,如果把做手机的精神投入到其他电器行业,那么这帮孙子就等着吃屎吧。

这是一个真实的故事。