[英]How to configure OData and Radzen Blazor (client and server) for Net Core 6 and Odata 8
Radzen documentation and examples for versions lower than Net Core 6 and Odata 8.低于 Net Core 6 和 Odata 8 的版本的 Radzen 文档和示例。
The first problem is in the response I get from server, does not match in return type.第一个问题是我从服务器得到的响应,返回类型不匹配。
The second filters第二个过滤器
Here is the service configuration:这是服务配置:
public async Task<ODataServiceResult<PersonDto>> GetPeopleAsync(string filter = default(string), int? top = default(int?), int? skip = default(int?), string orderby = default(string), string expand = default(string), string select = default(string), bool? count = default(bool?))
{
var uri = new Uri(http.BaseAddress, $"api/Persons");
uri = uri.GetODataUri(filter: filter, top: top, skip: skip, orderby: orderby, expand: expand, select: select, count: count);
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri);
var response = await http.SendAsync(httpRequestMessage);
return await response.ReadAsync<ODataServiceResult<PersonDto>>();
}
Here is the controller configuration:这是控制器配置:
[EnableQuery(MaxExpansionDepth = 10, MaxNodeCount = 1000)]
[HttpGet]
public IEnumerable<PersonDto> Get()
{
var people = context.Persons.ConvertToDto().AsQueryable();
return people;
}
Good if write query如果写查询很好
https://localhost:7069/api/Persons?$top=5&$skip=0&$count=true
in browser it works I get results(5) as expected.在浏览器中它可以正常工作,我得到了预期的结果(5)。
But for filters with query但是对于带有查询的过滤器
https://localhost:7069/api/Persons?$filter=(LastName+%3d%3d+null+%3f+%27%27+%3a+LastName).ToLower().Contains(%27s%27.ToLower())&$top=5&$skip=0&$count=true
I got this error :我收到了这个错误:
{"Message":"The query specified in the URI is not valid. ')' or operator expected at position 10 in '(LastName == null ? '' : LastName).ToLower().Contains('d'.ToLower ())'.","ExceptionMessage":"')'
{"Message":"URI 中指定的查询无效。')' 或 '(LastName == null ?'' : LastName).ToLower().Contains('d'.ToLower 中位置 10 处的运算符())'.","ExceptionMessage":"')'
On your API server:在您的 API 服务器上:
[HttpGet]
[EnableQuery]
public ActionResult<IQueryable<Person>> Get()
{
IQueryable<Person> items = entityService.AsQueryable();
return Ok(items);
}
builder.Services.AddControllers().AddOData(options =>
{
options.AddRouteComponents(routePrefix: "odata", GetEdmModel())
.Select()
.Count()
.Filter()
.Expand()
.OrderBy()
.SetMaxTop(maxTopValue: 100);
});
public static IEdmModel GetEdmModel()
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Person>(name: "Persons")
.EntityType.HasKey(person=> person.Id);
...
return builder.GetEdmModel();
}
public readonly struct ItemsPageResult<TItem>
{
public IEnumerable<TItem> Items { get; }
public int TotalItemsCount { get; }
public ItemsPageResult(IEnumerable<TItem> items, int totalItemsCount)
{
Items = items;
TotalItemsCount = totalItemsCount;
}
}
Your question shows your using a DTO which is fine.您的问题表明您使用 DTO 很好。 Be aware that your breaking a benefit of passing the query all the way back to the SQL engine if your using a provider that returns an IQueryable like EntityFramework does.
请注意,如果您使用像 EntityFramework 一样返回 IQueryable 的提供程序,那么您会破坏将查询一直传递回 SQL 引擎的好处。 If you want to map to a DTO, I suggest do it with an
Expression
, the nuget package AutoMapper can do this for you.如果你想映射到 DTO,我建议用
Expression
来做,nuget 包 AutoMapper 可以为你做这个。
In your client:在您的客户中:
public async ValueTask<ItemsPageResult<ItemContextResult<TItem>>> GetItemsAsync(
int startIndex,
int count,
CancellationToken cancellationToken) => await GetItemsAsync(startIndex, count, queryString: "", cancellationToken);
public async ValueTask<ItemsPageResult<ItemContextResult<TItem>>> GetItemsAsync(
int startIndex,
int count,
string queryString,
CancellationToken cancellationToken)
{
var query = $"odata/{EndPoint}?{queryString}&$skip={startIndex}&$top={count}&$count=true";
OdataResponce<TItem> response = await HttpClient.GetContentAsync<OdataResponce<TItem>>(relativeUrl: query, cancellationToken);
var contextItems = response.Items.Select((item, index) => new ItemContextResult<TItem>(item, index + startIndex)).ToList();
return new ItemsPageResult<ItemContextResult<TItem>>(contextItems, totalItemsCount: response.TotalItemsCount);
}
GetContentAsync
comes from RESTFulSense
change it to GetFromJsonAsync
for a plain HttpClient
. GetContentAsync
来自RESTFulSense
将其更改为GetFromJsonAsync
以获得普通的HttpClient
。
public readonly struct ItemContextResult<TItem>
{
public TItem Item { get; }
public int Offset { get; }
public ItemContextResult(TItem item, int offset)
{
Item = item;
Offset = offset;
}
}
public class OdataResponce<TItem>
{
[JsonPropertyName(name: "@odata.context")]
public string ContextUrl { get; set; } = null!;
[JsonPropertyName(name: "@odata.count")]
public int TotalItemsCount { get; set; }
[JsonPropertyName(name: "value")]
public IEnumerable<TItem> Items { get; set; } = null!;
}
The ItemContextResult
is not required its a little extra I add to get the relative line number into the result. ItemContextResult
不是必需的,我添加了一些额外的内容以将相对行号添加到结果中。
In my case this passes the Query to EntityFramework...在我的情况下,这会将查询传递给 EntityFramework ...
The comes from a solution where im using:来自我使用的解决方案:
<PackageReference Include="AutoMapper" Version="11.0.1" />
<PackageReference Include="Microsoft.AspNetCore.OData" Version="8.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.6" />
<PackageReference Include="RESTFulSense" Version="2.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.3.1" />
....
Client:客户:
<PackageReference Include="RESTFulSense.WebAssembly" Version="1.0.0" />
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.