简体   繁体   English

如何为 Net Core 6 和 Odata 8 配置 OData 和 Radzen Blazor(客户端和服务器)

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM