我将 odata 添加到启动和模型构建器中,我想测试它是否有效并返回 OData,因此我更新了控制器并将其更改为“ODataController”,然后我做了一个简单的 HttpGet 测试结果,但 URL:\n Text返回 404未找到\n文本返回 404 未找到\n和\n文本返回带有 json 对象的简单数组
\n这是我的代码
\n启动.cs
\n{\n public class Startup\n {\n public Startup(IConfiguration configuration)\n {\n Configuration = configuration;\n }\n\n public IConfiguration Configuration { get; }\n\n public void ConfigureServices(IServiceCollection services)\n { \n //connection avec MySql in the new projetc \n var connectionString = Configuration.GetConnectionString("DefaultConnection");\n services.AddDbContext<ApplicationDbContext>(options =>\n options.UseMySql(connectionString, new MySqlServerVersion(new Version(8, 0, 19)), mySqlOptions => mySqlOptions.CharSetBehavior(CharSetBehavior.NeverAppend)));\n\n services.AddDbContext<ApplicationDbContext>(opt => opt.UseInMemoryDatabase("commande_clt"));\n services.AddControllers().AddOData(opt => opt.AddRouteComponents("odata", GetEdmModel())); // Odata\n \n services.AddScoped<ITransaction, Transaction>();\n services.AddScoped<ICommandeClientServices, CommandeClientServices>();\n services.AddScoped<IArticleServices, ArticleServices>();\n services.AddScoped(typeof(IAppLogger), typeof(LoggerAdapter));\n services.AddScoped<IWebUserServices, WebUserServices>();\n \n services.AddTransient(typeof(IGenericRepository<>), typeof(GenericRepository<>));\n services.AddTransient(typeof(IGenericRepositoryReadOnly<>), typeof(GenericRepositoryReadOnly<>));\n \n services.AddScoped<IStocksDepotServices, StocksDepotServices>();\n services.AddScoped<IClientsServices, ClientsServices>();\n\n services.AddSwaggerGen(options =>\n {\n options.SwaggerDoc("CommandeOpenApi",\n new OpenApiInfo\n {\n Title = "Commande Client",\n Description = "D\xc3\xa9velopp\xc3\xa9 par HTSoft",\n Version = "1"\n });\n });\n\n var appSettingsSection = Configuration.GetSection("AppSettings");\n services.Configure<AppSettings>(appSettingsSection);\n var appSettings = appSettingsSection.Get<AppSettings>();\n var key = Encoding.ASCII.GetBytes(appSettings.secret);\n CommandeClientCleanArch.ApplicationCore.AppSettings.secret2 = appSettings.secret;\n services.AddAuthentication(x =>\n {\n x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;\n x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;\n })\n .AddJwtBearer(x =>\n {\n x.RequireHttpsMetadata = false;\n x.SaveToken = true;\n x.TokenValidationParameters = new TokenValidationParameters\n {\n ValidateIssuerSigningKey = true,\n\n IssuerSigningKey = new SymmetricSecurityKey(key),\n ValidateIssuer = false, //lors du d\xc3\xa9ploiyement cette variable doit etre true\n ValidateAudience = false //lors du d\xc3\xa9ploiyement cette variable doit etre true\n };\n });\n\n services.AddSwaggerGen(setup =>\n {\n // Include \'SecurityScheme\' to use JWT Authentication\n var jwtSecurityScheme = new OpenApiSecurityScheme\n {\n Scheme = "bearer",\n BearerFormat = "JWT",\n Name = "JWT Authentication",\n In = ParameterLocation.Header,\n Type = SecuritySchemeType.Http,\n Description = "Put **_ONLY_** your JWT Bearer token on textbox below!",\n\n Reference = new OpenApiReference\n {\n Id = JwtBearerDefaults.AuthenticationScheme,\n Type = ReferenceType.SecurityScheme\n }\n };\n setup.SwaggerDoc("v1", new OpenApiInfo { Title = "MyTestService", Version = "v1", });\n setup.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());\n setup.AddSecurityDefinition(jwtSecurityScheme.Reference.Id, jwtSecurityScheme);\n setup.AddSecurityRequirement(new OpenApiSecurityRequirement()\n {\n {\n new OpenApiSecurityScheme\n {\n Reference = new OpenApiReference\n {\n Type = ReferenceType.SecurityScheme,\n Id="Bearer"\n },\n Scheme="oauth2",\n Name="Bearer",\n In = ParameterLocation.Header,\n },\n new List<String>()\n }\n });\n });\n\n services.AddRouting();\n \n services.AddCors(options =>\n {\n options.AddPolicy("AllowAnyCorsPolicy", policy => policy.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin());\n });\n\n services.AddHttpClient();\n services.AddControllers();\n }\n\n // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n if (env.IsDevelopment())\n {\n AppSettings.IsDevelopment = true;\n app.UseDeveloperExceptionPage();\n app.UseSwagger();\n app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebApi v1"));\n }\n else\n {\n AppSettings.IsDevelopment = false;\n }\n app.UseDeveloperExceptionPage();\n app.UseHttpsRedirection();\n\n app.UseRouting();\n app.UseCors("AllowAnyCorsPolicy");\n app.UseAuthorization();\n \n app.UseEndpoints(endpoints =>\n {\n endpoints.MapControllers();\n });\n }\n\n private static IEdmModel GetEdmModel()\n {\n ODataConventionModelBuilder builder = new ODataConventionModelBuilder();\n builder.EntitySet<CommandeClt>("commande_clt");\n return builder.GetEdmModel();\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\nCommandeClientController.cs\n{\n[Route("api/[Controller]")]\n[EnableCors("AllowAnyCorsPolicy")]\n[ApiController]
\n //[Authorize]\n \n public class CommandeClientController : ODataController\n {\n private readonly ICommandeClientServices _CommandeClientServices;\n // private readonly IArticleServices _discountPromotionServices;\n\n public CommandeClientController(ICommandeClientServices CommandeClientService ,IArticleServices discountPromotionServices)\n {\n _CommandeClientServices = CommandeClientService;\n // _discountPromotionServices = discountPromotionServices;\n\n }\n \n [HttpPost("AjoutArticle")]\n //[Authorize(Roles = "User, Admin")]\n\n public IActionResult AjouterArticleCommande([FromBody] ArticleCommande a)\n {\n try\n {\n ArticleCommande unar = new ArticleCommande();\n unar.cod_art = "00-";\n \n unar.qte_cde = 4;\n unar.num_cde_clt = "BC BB 0018/21";\n \n\n if (unar.qte_cde <= 0)\n {\n throw new Exception("Erreur Saisie Quantit\xc3\xa9 Ajout\xc3\xa9e");\n }\n CommandeClt articleAjout\xc3\xa9 = _CommandeClientServices.AddArticle(unar);\n _CommandeClientServices.Commit();\n return Ok(articleAjout\xc3\xa9);\n }\n catch (Exception ex)\n {\n ModelState.AddModelError("Erreur Create Commande client Controller 11032021", $"{ex.Message}");\n return BadRequest(ex.Message);\n }\n }\n \n [HttpPost("SuppressionArticle")]\n //[Authorize(Roles = "User, Admin")]\n public IActionResult DeleteCommandeArticle([FromBody] ArticleCommande a)\n {\n try\n {\n CommandeClt articleSupprimer = _CommandeClientServices.RemoveArticle(a);\n _CommandeClientServices.Commit();\n return Ok(articleSupprimer);\n }\n catch (Exception ex)\n {\n ModelState.AddModelError("Erreur Create Commande client Controller 11032021", $"{ex.Message}");\n return BadRequest(ex.Message);\n }\n }\n \n [HttpPatch("UpdateArticle")]\n public IActionResult UpdateCommandeArticle([FromBody] ArticleCommande a)\n {\n try\n {\n CommandeClt articlemodifier = _CommandeClientServices.UpdateArticle(a);\n _CommandeClientServices.Commit();\n return Ok(articlemodifier);\n }\n catch (Exception ex)\n {\n ModelState.AddModelError("Erreur Update Commande client Controller 11032021", $"{ex.Message}");\n return BadRequest(ex.Message);\n }\n}\n [HttpPatch("UpdateCommande")]\n public IActionResult UpdateCommande([FromBody] CommandeClt commande)\n {\n try\n { \n CommandeClt commandeModifer = _CommandeClientServices.UpdateCommande(commande);\n _CommandeClientServices.Commit();\n return Ok(commandeModifer);\n }\n catch (Exception ex)\n {\n ModelState.AddModelError("Erreur Create Commande client Controller 11032021", $"{ex.Message}");\n return BadRequest(ex.Message);\n }\n\n\n }\n \n [HttpPost("Create")]\n //[Authorize(Roles = "Admin")]\n public IActionResult CreateCommande([FromBody] CommandeClt cmd)\n {\n try\n {\n _CommandeClientServices.BeginTransaction();\n\n CommandeClt c1 = new CommandeClt();\n c1 = new CommandeClt();\n c1.cod_clt = "4119351";\n c1.rais_soc_clt = "ADRF";\n c1.articles = new List<ArticleCommande>();\n \n \n\n\n if (cmd.cod_clt == null || cmd.cod_clt.Trim() == "")\n {\n throw new Exception("Code Client est tr\xc3\xa9s important ");\n }\n\n if (!ModelState.IsValid)\n {\n return BadRequest(ModelState);\n }\n CommandeClt commande = _CommandeClientServices.Create(c1);\n if (commande == null)\n {\n ModelState.AddModelError("", $"Erreur de creation du commande 20210312");\n return StatusCode(500, ModelState);\n }\n _CommandeClientServices.Commit();\n return Ok("Votre commande "+ commande.num_cde_clt+ " est cr\xc3\xa9\xc3\xa9e avec succ\xc3\xa8s");\n\n }\n\n catch (Exception ex)\n {\n ModelState.AddModelError("Erreur Create Commande client Controller 11032021", $"{ex.Message}");\n return BadRequest(ex.Message);\n }\n \n\n }\n\n /// <summary>\n /// Recup\xc3\xa9rer toutes les commandes, Cet API n\'est authoris\xc3\xa9 que par l\'administareur\n /// </summary>\n /// <returns></returns>\n\n\n /// <summary>\n /// Cet API permet de recup\xc3\xa9rer tout les commande du client, De plus on peux filtr\xc3\xa9 ses commandes soit par dates ou par etats\n \n \n [HttpGet]\n [EnableQuery]\n //[Authorize(Roles = "User\n\n public IActionResult GetCommandes(string codclt, DateTime datedebut, DateTime datefin , string etat = "")\n {\n try\n {\n\n codclt = "4119351";\n datedebut = new DateTime(2021, 7, 1);\n datefin = new DateTime(2021, 7, 20);\n //les variable de type DateTime ne jamais soient null !\n // pour dire que les date sont nul alors il faut qui il soient egaux \xc3\xa0 01 / 01 / 0001\n if (codclt == null || codclt.Trim()=="")\n {\n throw new Exception("Code client est obligatoire");\n }\n if(datefin < datedebut)\n {\n throw new Exception("Date Fin doit etre superieur a date Debut");\n }\n IQueryable<CommandeClt> CommandesFiltrees = _CommandeClientServices.GetCommandes(codclt, datedebut, datefin, etat);\n // if (CommandesFiltrees==null)\n {\n // return Ok("Pas de Commande pour ce Client");\n }\n return Ok(CommandesFiltrees);\n }\n catch(Exception ex)\n {\n ModelState.AddModelError("Erreur GetCommandes Commande client Controller 15032021", $"{ex.Message}");\n return BadRequest(ex.Message);\n }\n }\n \n /// <summary>\n /// Cet API est pour le le client WEB, ICI on Cr\xc3\xa9\xc3\xa9 une commande que si le client ne poss\xc3\xa8de pas une commande d\xc3\xa9ja cr\xc3\xa9\xc3\xa9e!! \n /// </summary>\n /// <param name="commande"></param>\n /// <returns></returns>\n [HttpPost("GetLastOrCreate")]\n //[Authorize(Roles = "User")]\n public IActionResult GetLastOrCreate([FromBody] CommandeClt commande)\n {\n try\n {\n if (commande.cod_clt == null || commande.cod_clt.Trim() == "")\n {\n throw new Exception("Code Client est tr\xc3\xa9s important !");\n }\n if (!ModelState.IsValid)\n {\n return BadRequest(ModelState);\n }\n CommandeClt getLastOrCreate = _CommandeClientServices.GetLastOrCreate(commande);\n if (getLastOrCreate == null)\n {\n ModelState.AddModelError("", $"erreur de creation du commande 20210314");\n return StatusCode(500, ModelState);\n }\n return Ok(getLastOrCreate);\n }\n catch (Exception ex)\n {\n ModelState.AddModelError("Erreur GetLastOrCerate Commande client Controller 11032021", $"{ex.Message}");\n return BadRequest(ex.Message);\n }\n }\n\n \n \n /// <summary>\n /// Cet API Permet d\'Annuler une CommandeClient\n /// </summary>\n /// <param name="num_cde_clt"></param>\n /// <returns></returns>\n [HttpPatch("AnnulerCommande")]\n public IActionResult AnnulerCommande(string num_cde_clt)\n {\n try\n {\n if (num_cde_clt == null)\n {\n throw new Exception("Vous devez saisie le num_cde_clt");\n }\n Boolean annulation = _CommandeClientServices.CancelCommande(num_cde_clt);\n if (annulation == false)\n {\n return BadRequest("l\'annulation n\'est pas effectu\xc3\xa9e! La Commande est deja Annul\xc3\xa9e");\n }\n _CommandeClientServices.Commit();\n return Ok("Commande est annul\xc3\xa9e");\n\n }\n catch (Exception ex)\n {\n ModelState.AddModelError("Erreur Annulation Commande client Controller 18032021", $"{ex.Message}");\n return BadRequest(ex.Message);\n }\n }\n /// <summary>\n /// Cet API permet de supprimer une CommandeClient , et donc supprimer tous les articles ajout\xc3\xa9e a cette CommandeClient\n /// </summary>\n /// <param name="num_cde_clt"></param>\n /// <returns></returns>\n [HttpDelete("SupprimerCommande")]\n public IActionResult DeleteCommande(string num_cde_clt)\n {\n try\n {\n //throw new Exception("Acces refus\xc3\xa9");\n //if(num_cde_clt== null || num_cde_clt.Trim() == "")\n //{\n // throw new Exception("Vous devez indiquer la commande \xc3\xa0 supprimer");\n //}\n //Boolean suppression = _CommandeClientServices.DeleteCommande(num_cde_clt);\n //if (suppression == false)\n //{\n // return BadRequest("la suppression n\'est pas effectu\xc3\xa9e! cette commande n\'existe pas");\n //}\n return Ok("Pas encore impl\xc3\xa9ment\xc3\xa9e");\n }\n catch (Exception ex)\n {\n ModelState.AddModelError("Erreur suppression Commande client Controller 21032021", $"{ex.Message}");\n return BadRequest(ex.Message);\n }\n }\n\n\n\n\n }\n\n\n\n\n}\nRun Code Online (Sandbox Code Playgroud)\nComandeClt.cs模型
\n{\n public partial class CommandeClt\n {\n \n [Key]\n public string num_cde_clt { get; set; }\n [Required(ErrorMessage ="code client est obligatoire")]\n public string cod_clt { get; set; }\n public string rais_soc_clt { get; set; }\n public string etat_cde { get; set; }\n public DateTime dat_cde { get; set; }\n public decimal totalht { get; set; }\n public decimal tva { get; set; }\n public decimal totalttc { get; set; }\n public string transporteur { get; set; }\n public string adresse { get; set; }\n public string societe { get; set; }\n [JsonIgnore]\n public TimeSpan time_cde { get; set; }\n public decimal net { get; set; }\n public decimal remise { get; set; }\n [JsonIgnore]\n public decimal fodec { get; set; }\n [JsonIgnore]\n public string username { get; set; }\n public DateTime dat_liv { get; set; }\n [JsonIgnore]\n public string typec { get; set; }\n [JsonIgnore]\n public string typeexport { get; set; }\n public ICollection<ArticleCommande> articles { get; set; }\n public string cod_dep { get; set; }\n public CommandeClt()\n {\n fodec = 0;\n remise = 0;\n totalht = 0;\n tva = 0;\n totalttc = 0;
我发现错误是来自odata v8的路由规则。
\n\n\n端点和 OData 路由模板之间关系的构建基于一组规则,这些规则称为 OData 路由约定。例如,当控制器名称 \xe2\x80\x9cCustomers\xe2\x80\x9d 是给定 Edm 模型中的实体集时,\xe2\x80\x9cCustomersController\xe2\x80\x9d 是 OData 控制器。\xe2\x80\x9cEntitySetName + Controller\xe2\x80\x9d 是 OData\n控制器名称约定之一。
\n
这意味着我们需要使控制器名称和 EdmModel 保持一致。例如,这是我在启动时的 EdmModel 设置:
\nprivate static IEdmModel GetEdmModel()\n {\n ODataConventionModelBuilder builder = new ODataConventionModelBuilder();\n builder.EntitySet<LocalMallUser>("Users");\n return builder.GetEdmModel();\n }\nRun Code Online (Sandbox Code Playgroud)\n这意味着我需要创建一个名为UsersController将 http 请求映射到 odata 控制器的控制器,这是我的控制器:
using Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.OData.Query;\nusing Microsoft.AspNetCore.OData.Routing.Controllers;\nusing WebApi2.Data;\n\nnamespace WebApi.Controllers\n{\n [Route("odata/[Controller]")]\n public class UsersController : ODataController\n {\n private readonly LocaldbContext _context;\n\n public UsersController(LocaldbContext context)\n {\n _context = context;\n }\n\n [EnableQuery]\n public IActionResult Get()\n {\n return Ok(_context.user);\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n启动时的ConfigureServices、AddRouteComponents确定路由前缀:
\npublic void ConfigureServices(IServiceCollection services)\n {\n services.AddDbContext<LocaldbContext>(options =>\n options.UseSqlServer(Configuration.GetConnectionString("Localtest")));\n services.AddControllers().AddOData(opt => opt.EnableQueryFeatures().AddRouteComponents("odata",GetEdmModel()));\n services.AddSwaggerGen(c =>\n {\n c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApi2", Version = "v1" });\n });\n //services.AddOData();\n }\nRun Code Online (Sandbox Code Playgroud)\n