ASP.NET MVC 搭建博客 Song Of The Sea

第五个博客上线了!

这次使用的是ASP.NET MVC + Bootstrap3 + SignalR + 百度地图api + ajax无刷新更新页面等等….

目标: Demo : http://hsdog.be-sunshine.cn

ASP搭建的一个博客(部分重构之前python写的博客,大部分新添加的内容):一只划水狗

但本网站仅供交流和娱乐学习用,因为没有对标签进行处理,所以很容易就会被攻陷的.回头有空了在添加标签过滤功能.

🙂

代码等回头有空的时候放上来~

预览:



ASP.NET API2 设计 RESTful API 服务端解决跨域

原理:

只需要在消息头中添加一句:
Access-Control-Allow-Origin *

即可.

解决方案是直接在nuget中安装 Microsoft Asp.Net Web Api 2.2 Cross-Origin

然后在App-Start/WebApiConfig.cs下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.Http.Cors;

namespace WAPI
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            //跨域配置
            config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
            // Web API configuration and services

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
}

即可.

ASP.NET API2 设计 RESTful API

Copyright @ DocsASP.NETASP.NET Web API

微软的官方文档

首先是新建ASP.NET api项目

然后是设计Model

Product.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WAPI.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Category { get; set; }
        public decimal Price { get; set; }
    }
}

编写Controller(路由)

ProductsController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

using WAPI.Models;

namespace WAPI.Controllers
{
    public class ProductsController : ApiController
    {
        // XXM => decimal类型小数
        Product[] products = new Product[]{
            new Product{ Id=1,Name="Tomato Soup",Category="Groceries",Price=1},
            new Product{ Id=2,Name="Yo-yo",Category="Toys",Price=3.75M},
            new Product{ Id=3,Name="Hammer",Category="Hardware",Price=16.99M}
        };

        public IEnumerable<Product> GetAllProducts()
        {
            return products;
        }

        public IHttpActionResult GetProduct(int id)
        {
            //容器.FirstOrDefault(Boolean) 返回满足条件的第一个元素,如未找到,返回默认值
            var product = products.FirstOrDefault((p) => p.Id == id);
            if (product == null)
            {
                //ApiController.NotFound()
                //即404界面
                return NotFound();
            }
            //正常返回
            return Ok(product);
        }
    }
}

最后通过编写前端界面,并使用JQuery来实现ajax传输,显示

index.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>Product App</title>
</head>
<body>
    <div>
        <h2>All Products</h2>
        <ul id="products"/>
    </div>
    <div>
        <h2>Search by ID</h2>
        <input type="text" id="prodId" size="5"/>
        <input type="button" value="Search" onclick="find();"/>
        <p id="product"/>
    </div>

    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.0.3.min.js"></script>
    <script>
        var uri = 'api/products';

        (document).ready(function () {             //Send an AJAX request             .getJSON(uri)
                .done(function (data) {
                    //On success,'data' contains a list of products.
                    .each(data, function (key, item) {                         //Add a list item for the product。                         ('<li>', { text: formatItem(item) }).appendTo(('#products'));                     });                 });         });           function formatItem(item) {             return item.Name + ': ' + item.Price;
        }

        function find() {
            var id = ('#prodId').val();             .getJSON(uri + '/' + id)
                .done(function (data) {
                    ('#product').text(formatItem(data));                 })                 .fail(function (jqXHR, textStatus, err) {                     ('#product').text('Error: ' + err);
                });
        }
    </script>
</body>
</html>

结果如下所示

关于使用ajax(JavaScript)+Flask(Python)+Canvas 上传画布(Canvas)图片并存储

因为想要做一个todo list的记事本app.其中有一个模块是使用Canvas做涂鸦.
其中有两个操作:

1.然后上传canvas的画布图片并保存到本地.

2.将对应画布的url传给画布,并绘制出来.

首先,Canvas画板的css和js是在Github上淘的一个,链接如下:

https://github.com/youknowznm/paint<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>paint</title> <link rel="stylesheet" href="./paint.css"> </head> <body> <div class="canvas-wrapper"> <ul class="doodle-colors"> <li data-color="black"></li> <li data-color="green"></li> <li data-color="yellow"></li> <li data-color="red"></li> <li data-color="white"></li> </ul> <ul class="doodle-controllers"> <li class="undo"></li> <li class="redo"></li> <li class="clear"></li> </ul> <canvas id="cv" class="doodle-content" width='500' height='500'></canvas> </div> <script src="https://cdn.jsdelivr.net/jquery/3.1.1/jquery.min.js"></script> <script src="./paint.js"></script> <script> window.onload = function() { let canvasEle = ('.doodle-content')[0]; let colorsEle = ('.doodle-colors')[0]; let controllersEle = $('.doodle-controllers')[0]; initCanvas(canvasEle, colorsEle, controllersEle, null); } function oc(){ let cav=document.getElementById('cv'); console.log(cav); let data=cav.toDataURL(); console.log(data); let img = document.createElement('img'); img.src = data; document.body.appendChild(img); let image=cav.toDataURL('image/jpeg'); window.location=image; } </script> </body> </html>

注意,我在代码中添加了一个JavaScript函数oc():

        function oc(){
            let cav=document.getElementById('cv');
            console.log(cav);
            let data=cav.toDataURL();
            console.log(data);
            let img = document.createElement('img');
            img.src = data;
            document.body.appendChild(img);
            let image=cav.toDataURL('image/jpeg');
            window.location=image;
        }

其中cav.toDataURL('type')即可以实现提取当前Canvas中的图片流信息.
然后我们尝试向后台发送Canvas图片的用base64加密的数据.
使用一个Button来发送post信息.
添加<button id="btn" >123</button>
button添加click事件:

(function(){     ('#btn').click(function(){
        let cav=document.getElementById('cv');
        let image=cav.toDataURL('image/jpeg');
        .post('/upload',{'data':image,'idx':223},function(result){             let canvasEle = ('.doodle-content')[0];
            let colorsEle = ('.doodle-colors')[0];             let controllersEle = ('.doodle-controllers')[0];
            initCanvas(canvasEle, colorsEle, controllersEle, result);
        })
    })
})

其中表单中data为图片加密信息,idx为假想当前记事本的id.
实践.发送post内容如下:

注意这里只是介绍了前台代码,让大家看一下发送的表单数据,如果没编写后台接受Post的Route的话是会返回404的.

然后在后台的View视图中添加相应的Route:

from . import main
from flask import Flask,render_template
from flask import make_response,render_template, session, redirect, url_for, current_app,abort,flash,request
import json,os,base64  

@main.route('/upload',methods=['POST'])
def upLoad():
    """
    disturbing by jq
    this method cannot work
    """
    files=request.values.get('data')
    f=request.form['data'][23:]
    ind=request.form['idx']
    imgdata=base64.b64decode(f)
    file=open('app/static/'+ind+'.jpg','wb')
    file.write(imgdata)
    file.close()
    return '/static/'+ind+'.jpg'

@main.route('/show',methods=['GET'])
def show():
    return render_template('index.html')

其中用request.values.get('key')来获取对应表单的数据.然后用base64算法对获取到的数据进行解码.之后创建一个空文件idx.jpg,将解码后的数据写进去.得到的即为图片.

我们可以看到获取到的data的头有一段非编码部分:

data:image/jpeg;base64,/9j/4A

所以我们需要将前面不属于编码的部分去掉.
后台处理代码中:

    f=request.form['data'][23:]

即完成了这一任务.

注意在JavaScript用这种方式获取Canvas的时候,开启管道时背景如果是透明,它会在转换成base64时自动补成#fff(纯黑色).
所以我们需要在创建Canvas时将背景染成纯白色#000.
我们在Paint.js中初始化context中加入下面两句:

    // 初始化 context
    var ctx = canvasEle.getContext('2d');
    ctx.fillStyle="#fff";
    ctx.fillRect(0, 0, 500, 500);

OK,我们获取图片后即为原图了!

至于如何在Canvas中将图片画出来.直接用paint.js中的 initCanvas(canvasEle, colorsEle, controllersEle, result);
即可.result为对应图片的地址一般是发布网站的相对地址.
上传结果:

最后一个问题:
当我们试图读取图片的url时,浏览器多半会返回对应url的缓存图片文件,如何解决这个问题呢?
我们只需要在URL中随便加入一个参数即可,保证每次的url不相同即可,比如:

URL=URL+'?t='+Math.random();

OK,日志本的第一个难题攻关!