博客 (8)

System.NotSupportedException: Serialization and deserialization of 'System.DateOnly' instances are not supported.

The unsupported member type is located on type 'System.Nullable`1[System.DateOnly]'.

解决方法:

https://www.nuget.org/packages/DateOnlyTimeOnly.AspNet/

builder.Services
    .AddControllers(options => options.UseDateOnlyTimeOnlyStringConverters())
    .AddJsonOptions(options => options.UseDateOnlyTimeOnlyStringConverters());


M
转自 Maksym Koshovyi 3 年前
4,192

最近,Microsoft 将其针对Web API 的默认序列化从 Newtonsoft JsonConvert 更改为 System.Text.Json JsonSerializer。

using System.Text.Json;
string s = JsonSerializer.Serialize(object);
var obj = JsonSerializer.Deserialize<T>(string);

System.Text.Json 命名空间:https://docs.microsoft.com/zh-cn/dotnet/api/system.text.json?view=net-5.0

如何从 Newtonsoft.Json 迁移到 System.Text.Json:https://docs.microsoft.com/zh-cn/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to?pivots=dotnet-5-0


不序列化属性

[System.Text.Json.Serialization.JsonIgnore]

当值为 null 时不序列化

[System.Text.Json.Serialization.JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]


格式化/美化

System.Text.Json.JsonSerializer.Serialize(Obj, new System.Text.Json.JsonSerializerOptions {
    WriteIndented = true
})


不编码中文(建议默认需要编码,可防止页面显示乱码,除非需要放在 <pre /> 标签中直接显示,可友好显示中文)

System.Text.Json.JsonSerializer.Serialize(Obj, new System.Text.Json.JsonSerializerOptions {
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
})


xoyozo 4 年前
5,921

本文不定时更新中……

收集了一些在开发过程中遇到的一些问题的解决方法,适合新手。


异常:

出现脚本错误或者未正确调用 Page()

原因:不小心删了第一行内容:<template>


异常:

模块编译失败:TypeError: Cannot read property 'for' of undefined

at fixDefaultIterator (D:\HBuilderX\plugins\uniapp\lib\mpvue-template-compiler\build.js:4277:24)

at mark (D:\HBuilderX\plugins\uniapp\lib\mpvue-template-compiler\build.js:4306:5)

at markComponent (D:\HBuilderX\plugins\uniapp\lib\mpvue-template-compiler\build.js:4371:5)

at baseCompile (D:\HBuilderX\plugins\uniapp\lib\mpvue-template-compiler\build.js:4384:15)

at compile (D:\HBuilderX\plugins\uniapp\lib\mpvue-template-compiler\build.js:4089:28)

at Object.module.exports (D:\HBuilderX\plugins\uniapp\lib\mpvue-loader\lib\template-compiler\index.js:43:18)

原因:新建的页面(简单模板)只有以下 3 个标签,须在 <template /> 中添加一些代码,如 <view />

<template>
</template>

<script>
</script>

<style>
</style>

异常:

模块编译失败:TypeError: Cannot read property 'toString' of undefined

at Object.preprocess (D:\HBuilderX\plugins\uniapp\lib\preprocess\lib\preprocess.js:56:15)

at Object.module.exports (D:\HBuilderX\plugins\uniapp\lib\preprocessor-loader.js:9:25)

原因:没有原因,纯抽风,HX 关掉再开就好了。


异常:

Cannot set property 'xxx' of undefined;at pages/... onLoad function;at api request success callback function

原因:属性未定义,例如 

data() {
	return {
		item: { }
	}
}

而直接赋值 this.item.abc.xxx = '123';

解决:

data() {
	return {
		item: {
			abc: ''
		}
	}
}

问:page 页面怎样修改 tabBar?

答:官方文档未给出答案,百度了一圈也无果(2018-10-23),但有人说小程序的 setTabBarBadge() 方法设置角标是可以用的。


坑:

VM1694:1 获取 wx.getUserInfo 接口后续将不再出现授权弹窗,请注意升级

参考文档: https://developers.weixin.qq.com/community/develop/doc/0000a26e1aca6012e896a517556c01

填坑:放弃使用 uni.getUserInfo 接口来获取用户信息,uni.login 可返回用于换取 openid / unionid 的 code,参:uni.login、 code2Session


坑:字符搜索(当前目录)(Ctrl+Alt+F)搜不出所有结果

填坑:顾名思义他只搜索当前目录,即当前打开文件所在目录,而非我误认为的整个项目根目录。在“项目管理器”中选中要搜索字符的目录即可。


坑:uni.navigateTo() 或 uni.redirectTo() 没反应

填坑:这两个方法不允许跳转到 tabbar 页面,用 uni.switchTab() 代替。


坑:使用“Ctrl+/”快捷键弹出“QQ五笔小字典”窗口

解决:打开QQ五笔“属性设置”,切换到“快捷键设置”选项卡,把“五笔小字典”前的勾取消(即使该组合键是设置为Ctrl+?)。


坑:<rich-text /> 中的 <img /> 太大,超出屏幕宽度

填坑:用正则表达式给 <img /> 加上最大宽度

data.data.Content = data.data.Content.replace(/\<img/gi, '<img style="max-width:100%;height:auto" ');

坑:无法重命名或删除目录或文件

填坑一:“以管理员身份运行”HBuilder X 后再试。

填坑二:关闭微信开发者工具、各种手机和模拟器后再试。

填坑三:打开“任务管理器”,结束所有“node.exe”进程后再试。


坑:

 thirdScriptError 
 sdk uncaught third Error 
 (intermediate value).$mount is not a function 
 TypeError: (intermediate value).$mount is not a function
Page[pages/xxxx/xxxx] not found. May be caused by: 1. Forgot to add page route in app.json. 2. Invoking Page() in async task.
Page is not constructed because it is not found.

填坑:关闭微信开发者工具、各种手机和模拟器后,删除“unpackage”目录。


坑:

Unexpected end of JSON input;at "pages/news/view" page lifeCycleMethod onLoad function
SyntaxError: Unexpected end of JSON input

填坑:给 uni.navigateTo() 的 url 传参时,如果简单地将对象序列化 JSON.stringify(item),那么如果内容中包含“=”等 url 特殊字符,就会发生在接收页面 onLoad() 中无法获取到完整的 json 对象,发生异常。

uni.navigateTo({
	url: "../news/view?item=" + JSON.stringify(item)
})

所以应该把参数值编码:

uni.navigateTo({
	url: "../news/view?item=" + escape(JSON.stringify(item))
})

如果是一般的 web 服务器来接收,那么会自动对参数进行解码,但 uni-app 不会,如果直接使用:

onLoad(e) {
	this.item = JSON.parse(e.item);
}

会发生异常:

Unexpected token % in JSON at position 0;at "pages/news/view" page lifeCycleMethod onLoad function
SyntaxError: Unexpected token % in JSON at position 0

需要解码一次:

onLoad(e) {
	this.item = JSON.parse(unescape(e.item));
}

需要注意的是,unescape(undefined) 会变成 'undefined',如果要判断是否 undefined,应是 unescape 之前。


坑:图片变形

填坑:mode="widthFix"


坑:页面如何向 tabBar 传参

填坑:全局或缓存


坑:编译为 H5 后,出现:Access-Control-Allow-Origin

填坑:参阅


坑:编译为 H5 后,GET 请求的 URL 中出现“?&”

填坑 :客户端只求 DCloud 官方能够尽快修复这个 bug,IIS 端可以暂时用 URL 重写来防止报 400 错误,参此文


坑:[system] errorHandler TypeError: Cannot read property 'forEach' of undefined

填坑:待填


xoyozo 6 年前
17,919

本文不定时更新中……


具备 RESTful 相关知识会更有利于学习 ASP.NET Web API:RESTful API 学习笔记

ASP.NET Web API 官网:https://www.asp.net/web-api


服务 URI Pattern

ActionHttp verbURI说明
Get contact listGET/api/contacts列表
Get filtered contactsGET/api/contacts?$top=2筛选列表
Get contact by IDGET/api/contacts/id获取一项
Create new contactPOST/api/contacts增加一项
Update a contactPUT/api/contacts/id修改一项
Delete a contactDELETE/api/contacts/id
删除一项


返回类型Web API 创建响应的方式
void返回空 204 (无内容)
HttpResponseMessage转换为直接 HTTP 响应消息。
IHttpActionResult调用 ExecuteAsync 来创建 HttpResponseMessage,然后将转换为 HTTP 响应消息。
其他类型将序列化的返回值写入到响应正文中;返回 200 (正常)。

HttpResponseMessage

可提供大量控制的响应消息。 例如,以下控制器操作设置的缓存控制标头。

public class ValuesController : ApiController
{
    public HttpResponseMessage Get()
    {
        HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, "value");
        response.Content = new StringContent("hello", Encoding.Unicode);
        response.Headers.CacheControl = new CacheControlHeaderValue()
        {
            MaxAge = TimeSpan.FromMinutes(20)
        };
        return response;
    } 
}

IHttpActionResult

public IHttpActionResult Get (int id)
{
    Product product = _repository.Get (id);
    if (product == null)
    {
        return NotFound(); // Returns a NotFoundResult
    }
    return Ok(product);  // Returns an OkNegotiatedContentResult
}

其他的返回类型

响应状态代码为 200 (正常)。此方法的缺点是,不能直接返回错误代码,如 404。 但是,您可以触发 HttpResponseException 的错误代码


完善 Help 页

一般都是通过元数据注释(Metadata Annotations)来实现的描述的。


显示接口和属性的描述:

打开 HelpPage 区域的 App_Start 目录下的 HelpPageConfig.cs 文件,在 Register 方法的首行取消注释行:

config.SetDocumentationProvider(new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml")));

在项目右键属性“生成”页,勾选“XML 文档文件”,并填写与上述一致的路径(App_Data/XmlDocument.xml)。


给接口加上 ResponseType 显示响应描述和示例:[ResponseType(typeof(TEntity))]


在实体模型的属性上加入 RequiredAttribute 特性可提供请求或响应中的实体的属性描述,如:[Required]


推荐使用:Swashbuckle

关于格式


在 WebApiConfig.Register() 中加入以下代码以禁止以 XML 格式输出(请按需设置):

GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();

Json 序列化去掉 k__BackingField

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver { IgnoreSerializableAttribute = true };

如果属性值为 null 则不序列化该属性

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };



xoyozo 6 年前
4,385

ASP.NET MVC 如果从控制器输出的是匿名类的集合,那么绑定到视图时会报错:

“object”未包含“xxx”的定义

简单的解决方法是 JSON 序列化再反序列化,例如:

ViewBag.list = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(q.ToList()));

上面是 ViewBag 的情形,如果是直接 return View(匿名类集合);

那么在视图页面:

@model IEnumerable<dynamic>


xoyozo 7 年前
3,735

本文记录 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,102

Session 有多种存储模式,默认是 InProc,顾名思义是“在进程内”,即在 IIS 中,随网站重启而重启,网站发布后(或改动 .dll 文件)会导致应用重新运行,Session 清空。

Session 可以使用 StateServer 来保存,需要服务器开启 ASP.NET State Service 服务,此种方式要求保存在 Session 的信息必须序列化,然后从 Session 中获取的时候也要反序列化,这就导致性能有略微的损失。

Session 还可以配置为 SQLServer,将 Session 存储在数据库中,同样需要序列化。

当配置为 Custom 时,可以在使用 Memcached、Redis 等第三方缓存技术来实现 Session 的管理,本文不作讨论。

Off 模式即关闭 Session,这种方式如果要实现用户登录功能,就必须依赖 Cookie 等来实现。

下面针对常见的三种模式进行比较:


InProcStateServerSQLServer
存储位置应用进程内ASP.NET State Service 服务SQL Server 数据库
远程存储不支持支持支持
存储格式
任意序列化的序列化的
可能导致重启(丢失)的情况

配置文件中 processModel 标签的 memoryLimit 属性;

Global.asax 或者 Web.config 文件被更改;

Bin 文件夹中的 Web 程序(DLL)被修改;

杀毒软件扫描了一些 .config 文件;

系统资源紧张进行资源回收导致 IIS 进程崩溃或重启等。

ASP.NET State Service 服务停止;-
Session_End() 事件
部署难度简单稍复杂

Web.config 配置示例

(<system.web> 节点内)

<sessionState mode="InProc" /><sessionState mode="StateServer" /><sessionState mode="SQLServer" sqlConnectionString ="data source=x.x.x.x; user id=[user]; password=[pwd]" />

因此,如果你仅仅为了标题所述的“每次发布后丢失 Session”而烦恼,那么推荐使用 StateServer 模式来存储 Session。


注:

如果 Session 的 Key 是在应用启动时随机生成的话,使用 StateServer 和 SQLServer 还是会“丢失” Session。

这是对 Session 的配置,对 Cache 无效。

xoyozo 7 年前
4,890

// 定义

public enum status { ready, ordered, printed }
public enum statusB { ready = 1, ordered = 3, printed = 5 }

// 将字符串转化为枚举类型

public static status? ConvertStringToEnum_status(string str)
{
  return str != null && Enum.IsDefined(typeof(status), str) ? (status)Enum.Parse(typeof(status), str) : null as status?;
}

// 将数字(索引值)转化为枚举类型

status s = (status)1; // 值为 status.ordered
statusB s = (statusB)1; // 值为 statusB.ready

// 将枚举类型转化为数字(索引值)

int s = (int)status.ordered; // 值为 1
int s = (int)statusB.ready; // 值为 1

// 循环

foreach (status s in Enum.GetValues(typeof(status)))
{
}


当无法序列化或需要序列化为字符串时,在定义枚举前加上:

当使用 System.Text.Json 时为:

[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))]

当使用 Newtonsoft.Json 时为:

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


xoyozo 8 年前
5,079