博客 (152)

代码一:

#if DEBUG
    // Debug 模式
#else
    // Release 模式
#endif

作用:判断 调试模式 / 发布模式

条件:须在项目属性的生成页中勾选“定义 DEBUG 常量”

适用:记录 EF 生成的 SQL 语句、控制定时器只在生产环境执行等

注意:调试和发布时应选择正确的模式


代码二:

if(Request.IsLocal) { }

作用:判断 本地 / 远程

条件:在会话中

适用:显示错误详情、记录 EF 生成的 SQL 语句

注意:不能用于定时器、Application_Start、异步操作等非会话中


代码三:

if (System.Net.IPAddress.IsLoopback(HttpContext.Connection.RemoteIpAddress)) { }

说明:ASP.NET Core 中的写法,用于检测 IP 地址是否为本地回环地址(IPv4 为 127.0.0.1,IPv6 为 ::1)

若在视图中使用,HttpContext 改为 ViewContext.HttpContext 或 Context

作用/条件/适用/注意:参“代码二”


代码四:

if(HttpRuntime.AppDomainAppPath == "X:\xxx\") { }

作用:判断当前网站根目录路径

条件:开发环境和生产环境的根目录路径不同

适用:判断根目录路径作相应的处理,适用于以上各种情况

注意:路径有变须要修改相应程序代码

xoyozo 6 年前
5,696

制作类似下图中的拖拽排序功能:

image.png

1. 首先数据库该表中添加字段 sort,类型为 double(MySQL 中为 double(0, 0))。

2. 页面输出绑定数据(以 ASP.NET MVC 控制器为例):

public ActionResult EditSort()
{
    if (!zConsole.Logined) { return RedirectToAction("", "SignIn", new { redirect = Request.Url.OriginalString }); }

    db_auto2018Entities db = new db_auto2018Entities();

    return View(db.dt_dealer.Where(c => c.enabled).OrderBy(c => c.sort));
}

这里可以加条件列出,即示例中 enabled == true 的数据。

3. 前台页面引用 jQuery 和 jQuery UI。

4. 使用 <ul /> 列出数据:

<ul id="sortable" class="list-group gutter list-group-lg list-group-sp">
    @foreach (var d in Model)
    {
        <li class="list-group-item" draggable="true" data-id="@d.id">
            <span class="pull-left"><i class="fa fa-sort text-muted fa m-r-sm"></i> </span>
            <div class="clear">
                【id=@d.id】@d.name_full
            </div>
        </li>
    }
</ul>

5. 初始化 sortable,当拖拽结束时保存次序:

<script>
    var url_SaveSort = '@Url.Action("SaveSort")';
</script>
<script>
    $("#sortable").sortable({
        stop: function (event, ui) {
            // console.log('index: ' + $(ui.item).index())
            // console.log('id: ' + $(ui.item).data('id'))
            // console.log('prev_id: ' + $(ui.item).prev().data('id'))
            $.post(url_SaveSort, {
                id: $(ui.item).data('id'),
                prev_id: $(ui.item).prev().data('id')
            }, function (json) {
                if (json.result.success) {
                    // window.location.reload();
                } else {
                    toastr["error"](json.result.info);
                }
            }, 'json');
        }
    });
    $("#sortable").disableSelection();
</script>

这里回传到服务端的参数为:当前项的 id 值、拖拽后其前面一项的 prev_id 值(若移至首项则 prev_id 为 undefined)。

不使用 $(ui.item).index() 是因为,在有筛选条件的结果集中排序时,使用该索引值配合 LINQ 的 .Skip 会引起取值错误。

6. 控制器接收并保存至数据库:

[HttpPost]
public ActionResult SaveSort(int id, int? prev_id)
{
    if (!zConsole.Logined)
    {
        return Json(new { result = new { success = false, msg = "请登录后重试!" } }, JsonRequestBehavior.AllowGet);
    }

    db_auto2018Entities db = new db_auto2018Entities();

    dt_dealer d = db.dt_dealer.Find(id);

    // 拖拽后其前项 sort 值(若无则 null)(此处不需要加 enabled 等筛选条件)
    double? prev_sort = prev_id.HasValue
        ? db.dt_dealer.Where(c => c.id == prev_id).Select(c => c.sort).Single()
        : null as double?;

    // 拖拽后其后项 sort 值(若无前项则取首项作为后项)(必须强制转化为 double?,否则无后项时会返回 0,导致逻辑错误)
    double? next_sort = prev_id.HasValue
        ? db.dt_dealer.Where(c => c.sort > prev_sort && c.id != id).OrderBy(c => c.sort).Select(c => (double?)c.sort).FirstOrDefault()
        : db.dt_dealer.Where(c => c.id != id).OrderBy(c => c.sort).Select(c => (double?)c.sort).FirstOrDefault();

    if (prev_sort.HasValue && next_sort.HasValue)
    {
        d.sort = (prev_sort.Value + next_sort.Value) / 2;
    }
    if (prev_sort == null && next_sort.HasValue)
    {
        d.sort = next_sort.Value - 1;
    }
    if (prev_sort.HasValue && next_sort == null)
    {
        d.sort = prev_sort.Value + 1;
    }

    db.SaveChanges();

    return Json(new { item = new { id = d.id }, result = new { success = true } });
}

需要注意的是,当往数据库添加新项时,必须将 sort 值设置为已存在的最大 sort 值 +1 或最小 sort 值 -1。

var d = new dt_dealer
{
    name_full = "新建项",
    sort = (db.dt_dealer.Max(c => (double?)c.sort) ?? 0) + 1,
};


xoyozo 6 年前
6,487

当我们初始化一个 Swiper 时,

var mySwiper = new Swiper ('.swiper-container');

如果页面上只有一个 .swiper-container,那么 mySwiper 是一个对象,如果有多个 .swiper-container,则 mySwiper 是一个数组。

处理不当会报以下错误:

Uncaught TypeError: Cannot read property 'appendSlide' of undefined

Uncaught TypeError: Cannot read property 'prependSlide' of undefined

xoyozo 6 年前
3,828

UEditor 的 ASP 版本在虚拟空间上传文件失败,提示“上传错误”或“上传失败,请重试”等,是因为其文件上传组件在创建目录时,没有网站目录外的访问权限。


例如上传文件的磁盘保存路径为:

D:\web\sitename\wwwroot\upload\20180523\123.jpg


百度编辑器的上传组件会依次判断以下目录是否存在,不存在则创建:

D:\

D:\web\

D:\web\sitename\

D:\web\sitename\wwwroot\

D:\web\sitename\wwwroot\upload\

D:\web\sitename\wwwroot\upload\20180523\


虚拟空间自动配置的网站根目录可能是:

D:\web\sitename\wwwroot\


所以,判断存在或创建以下目录没有问题:

D:\web\sitename\wwwroot\upload\

D:\web\sitename\wwwroot\upload\20180523\


但判断存在以下目录时会因为权限不足而失败:

D:\

D:\web\

D:\web\sitename\


解决方法是找到文件 asp/Uploader.Class.asp

找到 CheckOrCreatePath 这个 Function,替换为:

Private Function CheckOrCreatePath( ByVal path )    
   Set fs = Server.CreateObject("Scripting.FileSystemObject")    
   Dim parts    
   Dim root : root = Server.mappath("/") & "\"    
   parts = Split( Replace(path, root, ""), "\" )    
   path = root    
   For Each part in parts    
       path = path + part + "\"    
       If fs.FolderExists( path ) = False Then    
           fs.CreateFolder( path )    
       End If    
   Next    
End Function


另外,如果服务端无法通过 Request.Form 来接收该值,把 <form /> 放到 <table /> 外面试试。

或者绑定 contentChange 事件来赋值(不推荐):

ue.addListener("contentChange", function() {
    document.getElementsByName('xxxxxx')[0].value = ue.getContent();
});

此方法的缺点是,不是所有操作都能触发 contentChange 事件,比如剪切、上传图片等。

改进方法(推荐):在 form 提交之前赋值。

xoyozo 7 年前
4,827

一: 执行sql语句,返回受影响的行数

在mysql里面,如果没有影响,那么返回行数为  -1 ,sqlserver 里面  还没有测试过

 (var ctx =  MyDbContext())
{
    ctx.Database.ExecuteSqlCommand("");
}


二 : Database.SqlQuery<T>   EF5执行sql查询语句 Database.SqlQuery 带返回值

这个准确的说是  IEnumerable<T> SqlQuery<T>(string sql, params object[] parameters)  ,注意返回值是 IEnumerable

这个是执行sql语句,返回你想要的类型的列表

dbMain.Database.SqlQuery<int>("select max(UserId) from tb_user_account").First();


或者假如你自己有个类别

  PersonView
{      PersonID { ; ; }      Name { ; ; }
}


那么就可以直接返回这个 PersonView类

 (var ctx =  MyDbContext())
{
    var peopleViews = ctx.SqlQuery<PersonView>("").ToList();
}

直接返回你想要的数据. 例如这里是 List<PersonView> 列表


转自 梨花驿路 7 年前
4,685

“/”应用程序中的服务器错误。

无法为具有固定名称“MySql.Data.MySqlClient”的 ADO.NET 提供程序加载在应用程序配置文件中注册的实体框架提供程序类型“MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6, Version=6.10.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d”。请确保使用限定程序集的名称且该程序集对运行的应用程序可用。有关详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=260882。

打开 nuget,卸载并重新安装 MySql.Data 和 MySql.Data.Entity

如果没有效果,打开 web.config,检查是否多次定义了 MySql.Data.MySqlClient

xoyozo 7 年前
7,926

“/”应用程序中的服务器错误。

未能加载文件或程序集“MySql.Data.Entity.EF6, Version=6.10.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)


6.10.7 版本的 MySql.Data.Entity.EF6.dll 文件发布后会自动变成 6.10.6,文件大小一样,只要用 FTP 上传覆盖一下即可。

xoyozo 7 年前
5,303

EF 提供一个查询 SQL 日志的属性:

DbContext.Database.Log

该属性是一个委托。

最简单的用法是直接输出到控制台:

DbContext.Database.Log = Console.WriteLine;

WebFrom 中可以输出到页面:

DbContext.Database.Log = Response.Write;

该委托可以带一个参数,利用它可以输出简单格式化的日志信息:

DbContext.Database.Log = (sql) =>
{
    Console.WriteLine("查询开始");
    Console.WriteLine(sql);
    Console.WriteLine("查询结束");
};

上面是直接输出到控制台或页面,当然也可以保存到变量:

string s = "";
DbContext.Database.Log = (sql) =>
{
    s += sql;
};

当然还有更强大更广泛的使用方式,有兴趣可以参阅 Jeffcky 的文章

xoyozo 7 年前
7,324

函数功能:添加/修改/删除/获取 URL 中的参数(锚点敏感)

/// <summary>
/// 设置 URL 参数(设 value 为 undefined 或 null 删除该参数)
/// <param name="url">URL</param>
/// <param name="key">参数名</param>
/// <param name="value">参数值</param>
/// </summary>
function fn_set_url_param(url, key, value) {
    // 第一步:分离锚点
    var anchor = "";
    var anchor_index = url.indexOf("#");

    if (anchor_index >= 0) {
        anchor = url.substr(anchor_index);
        url = url.substr(0, anchor_index);
    }

    // 第二步:删除参数
    key = encodeURIComponent(key);
    var patt;

    // &key=value
    patt = new RegExp("\\&" + key + "=[^&]*", "gi");
    url = url.replace(patt, "");

    // ?key=value&okey=value  -> ?okey=value
    patt = new RegExp("\\?" + key + "=[^&]*\\&", "gi");
    url = url.replace(patt, "?");

    // ?key=value
    patt = new RegExp("\\?" + key + "=[^&]*$", "gi");
    url = url.replace(patt, "");

    // 第三步:追加参数
    if (value != undefined && value != null) {
        value = encodeURIComponent(value);
        url += (url.indexOf("?") >= 0 ? "&" : "?") + key + "=" + value;
    }

    // 第四步:连接锚点
    url += anchor;

    return url;
}

/// <summary>
/// 获取 URL 参数(无此参数返回 null,多次匹配使用“,”连接)
/// <param name="url">URL</param>
/// <param name="key">参数名</param>
/// </summary>
function fn_get_url_param(url, key) {
    key = encodeURIComponent(key);
    var patt = new RegExp("[?&]" + key + "=([^&#]*)", "gi");

    var values = [];

    while ((result = patt.exec(url)) != null) {
        values.push(decodeURIComponent(result[1]));
    }

    if (values.length > 0) {
        return values.join(",");
    } else {
        return null;
    }
}


调用示例:

var url = window.location.href;

// 设置参数
url = fn_set_url_param(url, 'a', 123);

// 获取参数
console.log(fn_get_url_param, url, 'a');


压缩版:

function fn_set_url_param(b,c,e){var a="";var f=b.indexOf("#");if(f>=0){a=b.substr(f);b=b.substr(0,f)}c=encodeURIComponent(c);var d;d=new RegExp("\\&"+c+"=[^&]*","gi");b=b.replace(d,"");d=new RegExp("\\?"+c+"=[^&]*\\&","gi");b=b.replace(d,"?");d=new RegExp("\\?"+c+"=[^&]*$","gi");b=b.replace(d,"");if(e!=undefined&&e!=null){e=encodeURIComponent(e);b+=(b.indexOf("?")>=0?"&":"?")+c+"="+e}b+=a;return b}
function fn_get_url_param(b,c){c=encodeURIComponent(c);var d=new RegExp("[?&]"+c+"=([^&#]*)","gi");var a=[];while((result=d.exec(b))!=null){a.push(decodeURIComponent(result[1]))}if(a.length>0){return a.join(",")}else{return null}};


xoyozo 7 年前
3,487

本文记录 Newtonsoft.Json 的用法,System.Text.Json 请参此文

如何在序列化时间类型时以“年-月-日 时:分:秒”的格式输出?

默认时间类型将序列化为:2017-11-10T18:48:14.1685763+08:00,我们只要 new 一个 IsoDateTimeConverter 即可改变时间类型的输出格式:

var dtc = new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" };
string b = JsonConvert.SerializeObject(DateTime.Now, dtc);


如何将对象序列化为可友好阅读的字符串?

序列化后的字符串默认是“紧凑型”的,如:{"a":1,"b":2}

可以将 Formatting 指定为 Indented 即可输出格式化后的字符串,例:

var obj = new { a = 1, b = 2 };
string a = JsonConvert.SerializeObject(obj, Formatting.Indented);

结果如下:

{

  "a": 1,

  "b": 2

}


枚举类型输出为字符串,而非索引值

[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]

更多用法参:https://www.cnblogs.com/DomoYao/p/Json.html


不序列化属性

[Newtonsoft.Json.JsonIgnore]

当值为 null 时不序列化

[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]


不序列化值为 null 的项

var jSetting = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };

JsonConvert.SerializeObject(obj, Formatting.Indented, jSetting);

xoyozo 7 年前
5,103