1

我在 DevExpress 网格中的特定行正确连接到 API 时遇到问题。

我认为问题出在 API 上,因为网格中的某些行我可以通过以太删除或编辑它们来操作。但是像上面提到的其他一些行不能被以太编辑或删除,但所有创建的新数据也可以被操纵。希望有人遇到过这个问题,我提供了一些代码和错误消息供大家查看。

网格的代码

@page "/FetchData"
@inject HttpClient Http

<h2>DevExpress Data Grid:</h2>
@if (customer == null)
{
<h1>thinking!?!?!?</h1>
}
else
{
    <DxDataGrid Data=@customer
                DataNavigationMode="@DataGridNavigationMode.VirtualScrolling"
                RowRemoving=@((dataItem) => OnRowRemoving(dataItem))
                RowUpdating=@((updatingDataItem, newValues) => OnRowUpdating(updatingDataItem, newValues))
                RowInserting=@((newValues) => OnRowInserting(newValues))>
        <DxDataGridCommandColumn Width="150px"></DxDataGridCommandColumn>
        <DxDataGridColumn Field=@nameof(Customer.CustomerId) Caption="ID"></DxDataGridColumn>
        <DxDataGridColumn field=@nameof(Customer.FirstName) Caption="FirstName"></DxDataGridColumn>
        <DxDataGridColumn Field=@nameof(Customer.LastName) Caption="LastName"></DxDataGridColumn>

    </DxDataGrid>

    <br />
    <br />

    <DxDataGrid Data=@customer
                PageSize=15
                RowRemoving=@((dataItem) => OnRowRemoving(dataItem))
                RowUpdating=@((updatingDataItem, newValues) => OnRowUpdating(updatingDataItem, newValues))
                RowInserting=@((newValues) => OnRowInserting(newValues))>
        <DxDataGridCommandColumn Width="150px"></DxDataGridCommandColumn>
        <DxDataGridColumn Field=@nameof(Customer.CustomerId) Caption="ID"></DxDataGridColumn>
        <DxDataGridColumn field=@nameof(Customer.FirstName) Caption="FirstName"></DxDataGridColumn>
        <DxDataGridColumn Field=@nameof(Customer.LastName) Caption="LastName"></DxDataGridColumn>

    </DxDataGrid>
}

@functions {

        Customer[] customer;
        Customer cust = new Customer();

    private const string APIServer = "http://Notrealapi.com/api/customers/";

    protected override async Task OnInitAsync()
    {
        customer = await Http.GetJsonAsync<Customer[]>("http://Notrealapi.com/api/customers/");
    }

    async void OnRowRemoving(Customer dataItem)
    {
        await Http.DeleteAsync("http://Notrealapi.com/api/customers/" + dataItem.CustomerId);
        customer = await Http.GetJsonAsync<Customer[]>("http://Notrealapi.com/api/customers/");
        StateHasChanged();
    }

    async void OnRowUpdating(Customer dataItem, Dictionary<string, object> newValue)
    {
        Dictionary<string, object> tempNewValues = new Dictionary<string, object>(newValue);
        cust = await Http.GetJsonAsync<Customer>("http://Notrealapi.com/api/customers/" + dataItem.CustomerId);
        foreach (var field in tempNewValues.Keys)
        {
            switch (field)
            {
                case "ID":
                    dataItem.CustomerId = (int)tempNewValues[field];
                    break;
                case "FirstName":
                    dataItem.FirstName = (string)tempNewValues[field];
                    break;
                case "LastName":
                    dataItem.LastName = (string)tempNewValues[field];
                    break;
            }
        }
        //dataItem.FirstName = cust.FirstName;
        //dataItem.LastName = cust.LastName;
        await Http.SendJsonAsync(HttpMethod.Put, "http://Notrealapi.com/api/customers/" + dataItem.CustomerId, dataItem);
        cust = new Customer();
        customer = await Http.GetJsonAsync<Customer[]>("http://Notrealapi.com/api/customers/");
        StateHasChanged();
    }

    async void OnRowInserting(Dictionary<string, object> newValue)
    {
        Dictionary<string, object> tempNewValues = new Dictionary<string, object>(newValue);
        cust = new Customer();
        await Http.SendJsonAsync(HttpMethod.Post, "http://Notrealapi.com/api/customers/", tempNewValues);
        cust = new Customer();
        customer = await Http.GetJsonAsync<Customer[]>("http://Notrealapi.com/api/customers/");
        StateHasChanged();
    }


    public class Customer
    {
        public int CustomerId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public string Phone { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string Zipcode { get; set; }
    }
}

来自 API Customer.cs 的一些代码

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace testsitegp.Models
{
    public partial class Customer
    {
        public Customer()
        {
            Order = new HashSet<Order>();
        }

        public int CustomerId { get; set; }
        [StringLength(50)]
        public string FirstName { get; set; }
        [StringLength(50)]
        public string LastName { get; set; }
        public string Email { get; set; }
        public string Phone { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string Zipcode { get; set; }

        public ICollection<Order> Order { get; set; }
    }
}

客户控制器.cs

using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Net;
using testsitegp.Models;
using testsitegp.contracts;
using Microsoft.AspNetCore.Cors;

namespace HPlusSportsAPI.Controllers
{
    [Produces("application/json")]
    [Route("api/Customers")]
    public class CustomersController : Controller
    {
        private readonly ICostomerRepository _customerRepository;

        public CustomersController(ICostomerRepository costomerRepository)
        {
            _customerRepository = costomerRepository;
        }

        private async Task<bool> CustomerExists(int id)
        {
            return await _customerRepository.Exists(id);

        }

        //[EnableCors("AnotherPolicy")]
        [HttpGet]
        [Produces(typeof(DbSet<Customer>))]
        public IActionResult GetCustomer()
        {
            var results = new ObjectResult(_customerRepository.GetAll())
            {
                StatusCode = (int)HttpStatusCode.OK
            };

            Request.HttpContext.Response.Headers.Add("X-Total-Count", _customerRepository.GetAll().Count().ToString());

            return results;
        }

        //[EnableCors("AnotherPolicy")]
        [HttpGet("{id}")]
        [Produces(typeof(Customer))]
        public async Task<IActionResult> GetCustomer([FromRoute] int id)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var customer = await _customerRepository.Find(id);

            if (customer == null)
            {
                return NotFound();
            }

            return Ok(customer);
        }

        //[EnableCors("AnotherPolicy")]
        [HttpPut("{id}")]
        [Produces(typeof(Customer))]
        public async Task<IActionResult> PutCustomer([FromRoute] int id, [FromBody] Customer customer)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            if (id != customer.CustomerId)
            {
                return BadRequest();
            }

            try
            {
                await _customerRepository.Update(customer);
                return Ok(customer);
            }
            catch (DbUpdateConcurrencyException)
            {
                if(!await CustomerExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }              
            }
        }

        //[EnableCors("AnotherPolicy")]
        [HttpPost]
        [Produces(typeof(Customer))]
        public async Task<IActionResult> PostCustomer([FromBody] Customer customer)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            await _customerRepository.Add(customer);

            return CreatedAtAction("GetCustomer", new { id = customer.CustomerId }, customer);
        }

        //[EnableCors("AnotherPolicy")]
        [HttpDelete("{id}")]
        [Produces(typeof(Customer))]
        public async Task<IActionResult> DeleteCustomer([FromRoute] int id)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            if (! await CustomerExists(id))
            {
                return NotFound();
            }

            await _customerRepository.Remove(id);

            return Ok();
        }
    }
}

CustomerRepository.cs

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using testsitegp.contracts;
using testsitegp.Models;

namespace testsitegp.repository
{
    public class CustomerRepository : ICostomerRepository
    {
        private H_Plus_SportsContext _context;

        public CustomerRepository(H_Plus_SportsContext context)
        {
            _context = context;
        }

        public async Task<Customer> Add(Customer customer)
        {
            await _context.Customer.AddAsync(customer);
            await _context.SaveChangesAsync();
            return customer;
        }

        public async Task<bool> Exists(int id)
        {
            return await _context.Customer.AnyAsync(c => c.CustomerId == id);
        }

        public async Task<Customer> Find(int id)
        {
            return await _context.Customer.Include(customer => customer.Order).SingleOrDefaultAsync(a => a.CustomerId == id);
        }

        public IEnumerable<Customer> GetAll()
        {
            return _context.Customer;
        }

        public async Task<Customer> Remove(int id)
        {
            var customer = await _context.Customer.SingleAsync(a => a.CustomerId == id);
            _context.Customer.Remove(customer);
            await _context.SaveChangesAsync();
            return customer;
        }

        public async Task<Customer> Update(Customer customer)
        {
            _context.Customer.Update(customer);
            await _context.SaveChangesAsync();
            return customer;
        }
    }
}

这是设置类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using testsitegp.Models;
using testsitegp.contracts;
using testsitegp.repository;
using H_Plus_Sports.Contracts;
using H_Plus_Sports.Repositories;

namespace testsitegp
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddScoped<ICostomerRepository, CustomerRepository>();
            services.AddScoped<IOrderItemRepository, OrderItemRepository>();
            services.AddScoped<IOrderRepository, OrderRepository>();
            services.AddScoped<IProductRepository, ProductRepository>();
            services.AddScoped<ISalespersonRepository, SalespersonRepository>();

           // services.AddCors(options =>
           //{
                //options.AddPolicy(MyAllowSpecificOrigins,
               // builder =>
                //{
                    //builder.WithOrigins("https://websitetestgp.azurewebsites.net", 
                        //"https://websitetest22.azurewebsites.net", 
                        //"https://websitetest23.azurewebsites.net",
                        //"http://goodtest.com",
                       // "http://localhost:57870")
                                        //.AllowAnyHeader()
                                        //.AllowAnyMethod();
               //});
               // options.AddPolicy("AnotherPolicy",
               // builder =>
                //{
                    //builder.WithOrigins("https://websitetestgp.azurewebsites.net", 
                        //"https://websitetest22.azurewebsites.net", 
                        //"https://websitetest23.azurewebsites.net",
                        //"http://goodtest.com",
                        //"http://localhost:57870")
                                        //.AllowAnyHeader()
                                        //.AllowAnyMethod();
              //  });
           // });

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            var connection = "Server=tcp:testsitegp.database.windows.net,1433;Initial Catalog=H_Plus_Sports;Persist Security Info=False;" +
                "User ID=_____;Password=______;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;";

            services.AddDbContext<H_Plus_SportsContext>(options => options.UseSqlServer(connection));
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }

            //app.UseCors(MyAllowSpecificOrigins);
            app.UseHttpsRedirection();
            app.UseMvc();
        }
    }
}

这是我尝试操作其中一个损坏的行时遇到的错误

blazor.server.js:15 [2019-08-01T12:48:22.608Z] 错误:System.IO.IOException:无法从传输连接读取数据:现有连接被远程主机强行关闭.. -- -> System.Net.Sockets.SocketException (10054):现有连接被远程主机强行关闭。--- 内部异常堆栈跟踪结束 --- 在 System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.GetResult(Int16 token) 在 System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancelToken) 在 System. System.Net.Http.HttpConnection.ChunkedEncodingReadStream.CopyToAsyncCore(Stream destination, CancellationToken cancelToken) 处的 Net.Http.HttpConnection.FillAsync() System.Net.Http.HttpClient.GetStringAsyncCore(Task1 getTask) at Microsoft.AspNetCore.Components.HttpClientJsonExtensions.GetJsonAsync[T](HttpClient httpClient, String requestUri) at Websitewithpopup.Pages.BigGrid.OnRowUpdating(Customer dataItem, Dictionary2 newValue) 在 Q:\testsite\WebsitewithpopupDemoHP\Websitewithpopup\Pages\BigGrid.razor:line 123 at System.Threading.Tasks.Task.<>c.b__139_0(Object state) at Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext。 ExecuteSynchronously(TaskCompletionSource`1 完成,SendOrPostCallback d,对象状态)在 Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext。<>c.<.cctor>b__23_0(对象状态)在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext,ContextCallback回调,对象状态)---从先前引发异常的位置结束堆栈跟踪---在 Microsoft.AspNetCore.Components.Rendering 的 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)。RendererSynchronizationContext.ExecuteBackground(WorkItem 项)

[2019-08-01T12:48:22.610Z] 信息:连接断开。

图一:

首次加载网格:

图二:

在损坏的数据行之一上按编辑后的网格

图 3:

在损坏的数据行的编辑框中按更新后的网格:

图四:

在其中一个工作数据行上按编辑后的网格

图 5:

在工作数据行的编辑框中按更新后的网格:

4

0 回答 0