Asp.net core 5 / Odata v8实现(控制器不返回Odata类型)响应

fir*_*dri 2 c# asp.net-core

我将 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}\n
Run Code Online (Sandbox Code Playgroud)\n

CommandeClientController.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}\n
Run Code Online (Sandbox Code Playgroud)\n

ComandeClt.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;

Tin*_*ang 5

我发现错误是来自odata v8的路由规则

\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
\n

这意味着我们需要使控制器名称和 EdmModel 保持一致。例如,这是我在启动时的 EdmModel 设置:

\n
private static IEdmModel GetEdmModel()\n        {\n            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();\n            builder.EntitySet<LocalMallUser>("Users");\n            return builder.GetEdmModel();\n        }\n
Run Code Online (Sandbox Code Playgroud)\n

这意味着我需要创建一个名为UsersController将 http 请求映射到 odata 控制器的控制器,这是我的控制器:

\n
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}\n
Run Code Online (Sandbox Code Playgroud)\n

在此输入图像描述

\n

启动时的ConfigureServices、AddRouteComponents确定路由前缀:

\n
public 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        }\n
Run Code Online (Sandbox Code Playgroud)\n