添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐

上一篇写的是使用静态基类方法的实现步骤:

使用dynamic (ExpandoObject)的好处就是可以动态组建返回类型, 之前使用的是ViewModel, 如果想返回结果的话, 肯定需要把ViewModel所有的属性都返回, 如果属性比较多, 就有可能造成性能和灵活性等问题. 而使用ExpandoObject(dynamic)就可以解决这个问题.

返回一个对象

返回一个dynamic类型的对象, 需要把所需要的属性从ViewModel抽取出来并转化成dynamic对象, 这里所需要的属性通常是从参数传进来的, 例如针对下面的CustomerViewModel类, 参数可能是这样的: "Name, Company":

using System;

using SalesApi.Core.Abstractions.DomainModels;

namespace SalesApi.ViewModels

public class CustomerViewModel: EntityBase

public string Company { get; set; }

public string Name { get; set; }

public DateTimeOffset EstablishmentTime { get; set; }

还需要一个Extension Method可以把对象按照需要的属性转化成dynamic类型:

using System;

using System.Collections.Generic;

using System.Dynamic;

using System.Reflection;

namespace SalesApi.Shared.Helpers

public static class ObjectExtensions

public static ExpandoObject ToDynamic<TSource>(this TSource source, string fields = null)

if (source == null)

throw new ArgumentNullException("source");

var dataShapedObject = new ExpandoObject();

if (string.IsNullOrWhiteSpace(fields))

// 所有的 public properties 应该包含在ExpandoObject里

var propertyInfos = typeof(TSource).GetProperties(BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

foreach (var propertyInfo in propertyInfos)

// 取得源对象上该property的值

var propertyValue = propertyInfo.GetValue(source);

// 为ExpandoObject添加field

((IDictionary<string, object>)dataShapedObject).Add(propertyInfo.Name, propertyValue);

return dataShapedObject;

// field是使用 "," 分割的, 这里是进行分割动作.

var fieldsAfterSplit = fields.Split(',');

foreach (var field in fieldsAfterSplit)

var propertyName = field.Trim();

// 使用反射来获取源对象上的property

// 需要包括public和实例属性, 并忽略大小写.

var propertyInfo = typeof(TSource).GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

if (propertyInfo == null)

throw new Exception($"没有在‘{typeof(TSource)}’上找到‘{propertyName}’这个Property");

// 取得源对象property的值

var propertyValue = propertyInfo.GetValue(source);

// 为ExpandoObject添加field

((IDictionary<string, object>)dataShapedObject).Add(propertyInfo.Name, propertyValue);

return dataShapedObject;

注意: 这里的逻辑是如果没有选择需要的属性的话, 那么就返回所有合适的属性.

然后在CustomerController里面:

首先创建为对象添加link的方法:

private IEnumerable<LinkViewModel> CreateLinksForCustomer(int id, string fields = null)

var links = new List<LinkViewModel>();

if (string.IsNullOrWhiteSpace(fields))

links.Add(

new LinkViewModel(_urlHelper.Link("GetCustomer", new { id = id }),

"self",

"GET"));

links.Add(

new LinkViewModel(_urlHelper.Link("GetCustomer", new { id = id, fields = fields }),

"self",

"GET"));

links.Add(

new LinkViewModel(_urlHelper.Link("DeleteCustomer", new { id = id              }),

"delete_customer",

"DELETE"));

links.Add(

new LinkViewModel(_urlHelper.Link("CreateCustomer", new { id = id }),

"create_customer",

"POST"));

return links;

针对返回一个对象, 添加了本身的连接, 添加的连接 以及 删除的连接.

然后修改Get和Post的Action:

[HttpGet]

[Route("{id}", Name = "GetCustomer")]

public async Task<IActionResult> Get(int id, string fields)

var item = await _customerRepository.GetSingleAsync(id);

if (item == null)

return NotFound();

var customerVm = Mapper.Map<CustomerViewModel>(item);

var links = CreateLinksForCustomer(id, fields);

var dynamicObject = customerVm.ToDynamic(fields) as IDictionary<string, object>;

dynamicObject.Add("links", links);

return Ok(dynamicObject);

[HttpPost(Name = "CreateCustomer")]

public async Task<IActionResult> Post([FromBody] CustomerViewModel customerVm)

if (customerVm == null)

return BadRequest();

if (!ModelState.IsValid)

return BadRequest(ModelState);

var newItem = Mapper.Map<Customer>(customerVm);

_customerRepository.Add(newItem);

if (!await UnitOfWork.SaveAsync())

return StatusCode(500, "保存时出错");

var vm = Mapper.Map<CustomerViewModel>(newItem);

var links = CreateLinksForCustomer(vm.Id);

var dynamicObject = vm.ToDynamic() as IDictionary<string, object>;

dynamicObject.Add("links", links);

return CreatedAtRoute("GetCustomer", new { id = dynamicObject["Id"] }, dynamicObject);

红色部分是相关的代码. 创建links之后把vm对象按照需要的属性转化成dynamic对象. 然后往这个dynamic对象里面添加links属性. 最后返回该对象.

下面测试一下.

POST:

由于POST方法里面没有选择任何fields, 所以返回所有的属性.

下面试一下GET:

再试一下GET, 选择几个fields:

OK, 效果都如预期.

但是有一个问题, 因为返回的json的Pascal case的(只有dynamic对象返回的是Pascal case, 其他ViewModel现在返回的都是camel case的), 而camel case才是更好的选择 .

所以在Startup里面可以这样设置:

services.AddMvc(options =>

options.ReturnHttpNotAcceptable = true;

// the default formatter is the first one in the list.

options.OutputFormatters.Remove(new XmlDataContractSerializerOutputFormatter());

// set authorization on all controllers or routes

var policy = new AuthorizationPolicyBuilder()

.RequireAuthenticatedUser()

.Build();

options.Filters.Add(new AuthorizeFilter(policy));

.AddJsonOptions(options =>

options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

.AddFluetValidations();

然后再试试:

首先编写创建links的方法:

private IEnumerable<LinkViewModel> CreateLinksForCustomers(string fields = null)

var links = new List<LinkViewModel>();

if (string.IsNullOrWhiteSpace(fields))

links.Add(

new LinkViewModel(_urlHelper.Link("GetAllCustomers", new { fields = fields }),

"self",

"GET"));

links.Add(

new LinkViewModel(_urlHelper.Link("GetAllCustomers", new { }),

"self",

"GET"));

return links;

这个很简单.

然后需要针对IEnumerable<T>类型创建把ViewModel转化成dynamic对象的Extension方法:

using System;

using System.Collections.Generic;

using System.Dynamic;

using System.Reflection;

namespace SalesApi.Shared.Helpers

public static class IEnumerableExtensions

public static IEnumerable<ExpandoObject> ToDynamicIEnumerable<TSource>(this IEnumerable<TSource> source, string fields)

if (source == null)

throw new ArgumentNullException("source");

var expandoObjectList = new List<ExpandoObject>();

var propertyInfoList = new List<PropertyInfo>();

if (string.IsNullOrWhiteSpace(fields))

var propertyInfos = typeof(TSource).GetProperties(BindingFlags.Public | BindingFlags.Instance);

propertyInfoList.AddRange(propertyInfos);

var fieldsAfterSplit = fields.Split(',');

foreach (var field in fieldsAfterSplit)

var propertyName = field.Trim();

var propertyInfo = typeof(TSource).GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

if (propertyInfo == null)

throw new Exception($"Property {propertyName} wasn't found on {typeof(TSource)}");

propertyInfoList.Add(propertyInfo);

foreach (TSource sourceObject in source)

var dataShapedObject = new ExpandoObject();

foreach (var propertyInfo in propertyInfoList)

var propertyValue = propertyInfo.GetValue(sourceObject);

((IDictionary<string, object>)dataShapedObject).Add(propertyInfo.Name, propertyValue);

expandoObjectList.Add(dataShapedObject);

return expandoObjectList;

注意: 反射的开销很大, 注意性能.

然后修改GetAll方法:

[HttpGet(Name = "GetAllCustomers")]

public async Task<IActionResult> GetAll(string fields)

var items = await _customerRepository.GetAllAsync();

var results = Mapper.Map<IEnumerable<CustomerViewModel>>(items);

var dynamicList = results.ToDynamicIEnumerable(fields);

var links = CreateLinksForCustomers(fields);

var dynamicListWithLinks = dynamicList.Select(customer =>

var customerDictionary = customer as IDictionary<string, object>;

var customerLinks = CreateLinksForCustomer(

(int)customerDictionary["Id"], fields);

customerDictionary.Add("links", customerLinks);

return customerDictionary;

var resultWithLink = new {

Value = dynamicListWithLinks,

Links = links

return Ok(resultWithLink);

红色部分是相关代码.

测试一下:

不选择属性:

选择部分属性:

HATEOAS这部分就写到这.

其实 翻页的逻辑很适合使用HATEOAS结构. 有空我再写一个翻页的吧.

原文地址 https://www.cnblogs.com/cgzl/p/8745631.html

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

上一篇写的是使用静态基类方法的实现步骤: 使用dynamic (ExpandoObject)的好处就是可以动态组建返回类型, 之前使用的是ViewModel, 如果想返回结果的话, 肯定需要把ViewModel所有的属性都返回, 如果属性比较多, 就有可能造成性能和灵活性等问题. 而使用ExpandoObject(dynamic)就可以解决这个问题.返回一个对象返回一个dynamic类型的对象,
使用 ASP.NET Core 进行动态依赖注入 使用 asp.net 核心进行动态依赖注入的示例。 该教程位于。 ASP.NET Core 具有内置的依赖项注入。因此,您可以在控制器中提及接口 类型 ,而 ASP.NET Core 将在运行时提供接口的实际对象。 为此,您需要在启动类中编写一些配置。 我有一个简单的控制器和服务类。 我想在控制器内部 使用 服务类。 我可以在控制器的构造函数中提及服务接口 类型 。 另外,我需要在启动类中注册服务,以便 ASP.NET Core 可以在运行时中提供实际的 类型 。 public interface IService string GetHello ( string name ); public class Service : IService public string GetHello ( string name )
来自这里:http://stackoverflow.com/questions/3142495/deserialize-json-into-c-sharp- dynamic -object If you are happy to have a dependency upon theSystem.Web.Helpersassembly, then you can use theJsonclas...
从 Net 4.5版本 迁移至Net Core 3.1时,Web Api 中直接 dynamic 传参, 使用 会报错,错误信息如下: {"'System.Text.Json.JsonElement' does not contain a definition for 'LoginName'"} System.Exception {Microsoft.CSharp.RuntimeBinder.RuntimeBinderException} 而 在Net 4.5版本版本下不会报错, 使用 正常。报错代码如下:
.NET Core 3.0+ Web Api dynamic 类型 参数中ValueKind处理方法 导致原因:.Net Core 3.0+默认的对象序列化解析程序为System.Text.Json下的JsonDocument 解决办法:将默认的序列化程序System.Text.Json替换为Newtonsoft.Json 1.NuGet引入包:Microsoft.AspNet Core .Mvc.NewtonsoftJson 2.Startup添加命名空间:using Newtonsoft.Json.Serializat
public final class Integer extends Number implements Comparable<Integer> Integer类被final修饰,不能被继承。 继承了 Number 类,我们先看一下Number类有哪些方法: 这里就明白了,Integer由于继承了Number类,所以也有了这些方法。 另外,Integer 还 实现 了 Comparable接口,重写了compareTo()方法,
这段时间闲赋在家,感觉手痒,故想折腾一些东西. 由于之前移植了一个c#版本的spring cloud feign客户端(https://github.com/daixinkai/feign.net),所以想弄个配套的服务端动态接口, 实现 服务即接口的功能.虽然ABP框架内部包含一个功能强大的 Dynamic Web Api ,但是我只是想要一个独立简单的组件,用来 实现 以下效果: 原文地址:http:// asp.net -hacker.rocks/2016/02/18/extending-razor-views.html 作者:Jürgen Gutsch 翻译:杨晓东(Savorboard) 现在,已经有很多种方式来扩展Razor视图了,我们循循渐进,先从最简单的开始。 如果你之前熟悉MVC5(以及之前的MVC)中的视图的话,有一部分你应该已经很熟悉了。在新的ASP.NE...
本篇和大家分享的是一个 并发请求工具,并发往往代表的就是压力,对于一些订单量比较多的公司这种情况很普遍,也因此出现了很多应对并发的解决方案如:分布式,队列,数据库锁等; 对于没有遇到过或者不可能线上来处理并发问题的我们来说,需要模拟这种环境,不错这就是写并发请求工具的目的: . 对于 api 接口做并发请求 . Net Core 来写的能跨平台运行 . 允许配置多个目标地址,进行同时并发请求
PHP 可以通过 使用 现有的 Web 框架或手动编写代码来 实现 RESTful API 。 一种常用的方法是 使用 Laravel 框架,它提供了一组强大的工具来简化 RESTful API 的开发过程。您可以 使用 Artisan 命令行工具生成资源控制器,并通过定义路由和请求方法来处理 HTTP 请求。 如果您希望手动编写代码,可以 使用 PHP 的内置 Web 服务器和库,如 Slim 框架或者纯 PHP 代码 实现 。您可以根据请求方法(GET、POST、PUT、DELETE)执行不同的操作,并 使用 HTTP 状态代码和 JSON 数据格式返回响应。 总体而言, 实现 RESTful API 并不复杂,只需要熟悉 HTTP 协议和 API 开发的基本概念即可。