繁体   English   中英

Post方法返回405方法不允许在Angular 8 web api项目中使用

[英]Post method returning 405 Method not allowed in Angular 8 web api project

我的 register.service.ts 中的 post 方法有问题,因为它应该返回 200 OK,但它返回 405 方法不允许。 我为此错误苦苦挣扎了一段时间,我知道这一点,因为我必须在标头配置和 CORS 中间件中允许它。 我创建了一个中间件类,我将它与其他 CORS 配置一起在 startup.cs 中传递,如下所示:

  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.AddDbContext<DataContext>(options => options.UseMySql(Configuration.GetConnectionString("DataContext")));
            services.AddControllersWithViews();
            services.AddApiVersioning(options =>
 {
  options.UseApiBehavior = false;
  options.AssumeDefaultVersionWhenUnspecified = true;
 });
     services.AddCors(options =>
{
    options.AddPolicy(MyAllowSpecificOrigins,
        builder => builder.WithOrigins("http://localhost:5001").AllowAnyHeader().AllowAnyMethod());

            // In production, the Angular files will be served from this directory
            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "ClientApp/dist/";
            });


});
 services.AddScoped(typeof(IUserService<>), typeof(UserService<>));
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }


            app.UseHttpsRedirection();
            app.UseStaticFiles();
            if (!env.IsDevelopment())
            {
                app.UseSpaStaticFiles();
            }
 app.UseOptions();//this is the method from the CORS middleware class
            app.UseRouting();

            app.UseCors(MyAllowSpecificOrigins);
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller}/{action=Index}/{id?}");
            });

            app.UseSpa(spa =>
            {
                // To learn more about options for serving an Angular SPA from ASP.NET Core,
                // see https://go.microsoft.com/fwlink/?linkid=864501

                spa.Options.SourcePath = "ClientApp";

                if (env.IsDevelopment())
                {
                    spa.UseAngularCliServer(npmScript: "start");
                }
            });
        }
    }

这是 register.service.ts:

import { Injectable } from '@angular/core';
import { HttpClient, HttpClientModule, HttpHeaders } from '@angular/common/http';
import { environment } from 'src/environments/environment'; import { Register } from '../Models/register';
import { Observable, throwError } from 'rxjs';
import { retry, catchError } from 'rxjs/operators';




@Injectable({
  providedIn: 'root'
})
export class RegisterService {

baseurl = 'https://localhost:5001';
  constructor(private http: HttpClient) { }
Create(user): Observable<Register> {
  const httpOptions = { headers: new HttpHeaders({ 'Content-Type':
  'application/x-www-form-urlencoded', 'Access-Control-Allow-Headers': 'Authorization',
  'Access-Control-Allow-Methods': 'GET, POST, OPTIONS'})};
  return this.http.post<Register>(this.baseurl + '/register', JSON.stringify(user),
  httpOptions).pipe(retry(1), catchError(this.errorHandler));
  }

GetById(id: number) {
  let reqHeader = new HttpHeaders();
  return this.http.post(this.baseurl + '/register/' + id , {headers: reqHeader});
}
GetAll() {
  let reqHeader = new HttpHeaders();
  return this.http.get(this.baseurl + '/register/', {headers: reqHeader});
}
Update(user: Register) {
  let reqHeader = new HttpHeaders();
  return this.http.post(this.baseurl + '/register/editUser', user, {headers: reqHeader});
}
Delete(id: number) {
  let reqHeader = new HttpHeaders();
  return this.http.get(this.baseurl  + '/register/deleteUser/' + id, {headers: reqHeader});
}
errorHandler(error) {
  let errorMessage = '';
  if (error.error instanceof ErrorEvent) {
    // Get client-side error
    errorMessage = error.error.message;
  } else {
    // Get server-side error
    errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
  }
  console.log(errorMessage);
  return throwError(errorMessage);
}
}

我还用 application/json 替换了 x-www-form-urlencoded,但它在浏览器和邮递员中都有相同的行为。

这是 RegisterController.cs 类:

  [EnableCors]
[Produces("application/json")]
    [Route("[controller]")]
    [ApiController]
    public class RegisterController : ControllerBase
    {
        private readonly DataContext _context;
         private readonly IUserService<Register> _repo;
        public RegisterController(DataContext context,IUserService<Register> repo)
        {
            _context = context;
            _repo=repo;
        }

        // GET: api/Register
        [HttpGet]
        public async Task<ActionResult<IEnumerable<Register>>> Getregistrations()
        {
            return await _context.register.ToListAsync();
        }

        // GET: api/Register/5
        [HttpGet("{id}")]
        public async Task<ActionResult<Register>> GetRegister([FromRoute]int id)
        {
            if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        var user = await _context.register.FindAsync(id);

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

        return Ok(user);
        }

        // PUT: api/Register/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for
        // more details see https://aka.ms/RazorPagesCRUD.
        [HttpPut("{id}")]
        public async Task<IActionResult> PutRegister([FromRoute]int id,[FromBody] Register register)
        {
            if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        if (id != register.Id)
        {
            return BadRequest();
        }

        _context.Entry(register).State = EntityState.Modified;

        try
        {
            _repo.Update(register);
            var save = await _repo.SaveAsync(register);
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!RegisterExists(id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }

        return NoContent();
        }

        // POST: api/Register
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for
        // more details see https://aka.ms/RazorPagesCRUD.


        [Route("PostRegister")]
        [HttpPost]
        [HttpOptions]
        public async Task<ActionResult<Register>> PostRegister([FromBody] Register register)
        {
            if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        _repo.Add(register);
        var save = await _repo.SaveAsync(register);
             return CreatedAtAction(nameof(GetRegister), new { id = register.Id }, register);
        }

        // DELETE: api/Register/5
        [HttpDelete("{id}")]
        public async Task<ActionResult<Register>> DeleteRegister([FromRoute]int id)
        {
         if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        var user = await _context.register.FindAsync(id);
        if (user == null)
        {
            return NotFound();
        }

        _repo.Delete(user);
        var save = await _repo.SaveAsync(user);

        return Ok(user);
        }

        private bool RegisterExists(int id)
        {
            return _context.register.Any(e => e.Id == id);
        }


    }

我不知道为什么它不起作用。 有人可以帮我弄清楚吗? 如果您需要更多详细信息,请告诉我。

更新:

我已经尝试了 sam 的建议,我得到了与以前相同的结果:This is in Postman: Postman result for POST这是来自浏览器: Browser result

更新 2:在尝试使用 [FromForm] 而不是 [FromBody] 作为标题后:对于https://localhost:5001/register得到相同的错误 405 for https://localhost:5001/register/PostRegister得到 500 for注册/发布注册

我忘了指定我的路由路径配置为https://localhost:5001/Add STACKTRACE:

 fail: Microsoft.EntityFrameworkCore.Database.Command[20102] Failed executing DbCommand (53ms) [Parameters=[@p0='?' (Size = 4000), @p1='?' (Size = 4000), @p2='?' (Size = 4000)], CommandType='Text', CommandTimeout='30'] INSERT INTO `register` (`Email`, `Name`, `Password`) VALUES (@p0, @p1, @p2); SELECT `Id` FROM `register` WHERE ROW_COUNT() = 1 AND `Id` = LAST_INSERT_ID(); fail: Microsoft.EntityFrameworkCore.Update[10000] An exception occurred in the database while saving changes for context type 'AnotherAP.Helpers.DataContext'. Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> MySql.Data.MySqlClient.MySqlException (0x80004005): Column 'email' cannot be null ---> MySql.Data.MySqlClient.MySqlException (0x80004005): Column 'email' cannot be null at MySqlConnector.Core.ServerSession.ReceiveReplyAsyncAwaited(ValueTask`1 task) in C:\\projects\\mysqlconnector\\src\\MySqlConnector\\Core\\ServerSession.cs:line 774 at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) in C:\\projects\\mysqlconnector\\src\\MySqlConnector\\Core\\ResultSet.cs:line 49 at MySql.Data.MySqlClient.MySqlDataReader.ActivateResultSet() in C:\\projects\\mysqlconnector\\src\\MySqlConnector\\MySql.Data.MySqlClient\\MySqlDataReader.cs:line 130 at MySql.Data.MySqlClient.MySqlDataReader.CreateAsync(CommandListPosition commandListPosition, ICommandPayloadCreator payloadCreator, IDictionary`2 cachedProcedures, IMySqlCommand command, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\\projects\\mysqlconnector\\src\\MySqlConnector\\MySql.Data.MySqlClient\\MySqlDataReader.cs:line 391 at MySqlConnector.Core.CommandExecutor.ExecuteReaderAsync(IReadOnlyList`1 commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\\projects\\mysqlconnector\\src\\MySqlConnector\\Core\\CommandExecutor.cs:line 62 at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken) --- End of inner exception stack trace --- at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(DbContext _, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken) at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken) Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> MySql.Data.MySqlClient.MySqlException (0x80004005): Column 'email' cannot be null ---> MySql.Data.MySqlClient.MySqlException (0x80004005): Column 'email' cannot be null at MySqlConnector.Core.ServerSession.ReceiveReplyAsyncAwaited(ValueTask`1 task) in C:\\projects\\mysqlconnector\\src\\MySqlConnector\\Core\\ServerSession.cs:line 774 at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) in C:\\projects\\mysqlconnector\\src\\MySqlConnector\\Core\\ResultSet.cs:line 49 at MySql.Data.MySqlClient.MySqlDataReader.ActivateResultSet() in C:\\projects\\mysqlconnector\\src\\MySqlConnector\\MySql.Data.MySqlClient\\MySqlDataReader.cs:line 130 at MySql.Data.MySqlClient.MySqlDataReader.CreateAsync(CommandListPosition commandListPosition, ICommandPayloadCreator payloadCreator, IDictionary`2 cachedProcedures, IMySqlCommand command, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\\projects\\mysqlconnector\\src\\MySqlConnector\\MySql.Data.MySqlClient\\MySqlDataReader.cs:line 391 at MySqlConnector.Core.CommandExecutor.ExecuteReaderAsync(IReadOnlyList`1 commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\\projects\\mysqlconnector\\src\\MySqlConnector\\Core\\CommandExecutor.cs:line 62 at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken) --- End of inner exception stack trace --- at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(DbContext _, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken) at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken) fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1] An unhandled exception has occurred while executing the request. Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> MySql.Data.MySqlClient.MySqlException (0x80004005): Column 'email' cannot be null ---> MySql.Data.MySqlClient.MySqlException (0x80004005): Column 'email' cannot be null at MySqlConnector.Core.ServerSession.ReceiveReplyAsyncAwaited(ValueTask`1 task) in C:\\projects\\mysqlconnector\\src\\MySqlConnector\\Core\\ServerSession.cs:line 774 at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) in C:\\projects\\mysqlconnector\\src\\MySqlConnector\\Core\\ResultSet.cs:line 49 at MySql.Data.MySqlClient.MySqlDataReader.ActivateResultSet() in C:\\projects\\mysqlconnector\\src\\MySqlConnector\\MySql.Data.MySqlClient\\MySqlDataReader.cs:line 130 at MySql.Data.MySqlClient.MySqlDataReader.CreateAsync(CommandListPosition commandListPosition, ICommandPayloadCreator payloadCreator, IDictionary`2 cachedProcedures, IMySqlCommand command, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\\projects\\mysqlconnector\\src\\MySqlConnector\\MySql.Data.MySqlClient\\MySqlDataReader.cs:line 391 at MySqlConnector.Core.CommandExecutor.ExecuteReaderAsync(IReadOnlyList`1 commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\\projects\\mysqlconnector\\src\\MySqlConnector\\Core\\CommandExecutor.cs:line 62 at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken) --- End of inner exception stack trace --- at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(DbContext _, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken) at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken) at AnotherAP.Helpers.UserService`1.SaveAsync(T entity) in /Users/Chsyn/Projects/copyofAAP/AnotherAP/Helpers/UserService.cs:line 35 at AnotherAP.Controllers.RegisterController.PostRegister(Register register) in /Users/Chsyn/Projects/copyofAAP/AnotherAP/Controllers/RegisterController.cs:line 110 at lambda_method(Closure , Object ) at Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable.Awaiter.GetResult() at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)

这就是我的 Create() 方法现在在 register.service.ts 中的样子:

 baseurl = 'https://localhost:5001'; constructor(private http: HttpClient) { } Create(user): Observable<Register> { const httpOptions = { headers: new HttpHeaders( { 'Content-Type': 'application/json', 'Accept': 'application/json' }) }; return this.http.post<Register>(this.baseurl + '/register/Add' , JSON.stringify(user), httpOptions).pipe(retry(1), catchError(this.errorHandler)); }

您可以尝试如下修改 httpOptions 吗,请在尝试后发布您的观察结果:

const httpOptions = { headers: new HttpHeaders(
                             { 'Content-Type': 'application/json, application/x-www-form-urlencoded', 
                             { 'Accept': 'application/json, text/plain, */*', 
                               /*'Access-Control-Allow-Headers': 'Authorization',
                               'Access-Control-Allow-Methods': 'GET, POST, OPTIONS'*/
                             })
                    };
  return this.http.post<Register>(this.baseurl, JSON.stringify(user),
  httpOptions).pipe(retry(1), catchError(this.errorHandler));
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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