【问题标题】:Asp.net core 5 / Odata v8 implementation (controller not returning Odata type) in responseAsp.net core 5 / Odata v8 实现(控制器不返回 Odata 类型)作为响应
【发布时间】:2022-01-28 05:51:31
【问题描述】:

我将 odata 添加到启动和模型构建器中,我想测试它是否有效并返回 OData,因此我更新了控制器并将其更改为“ODataController”,然后我做了一个简单的 HttpGet 测试结果,但 URL: Text 返回 404 未找到 Text 未找到返回 404 和 Text 返回一个带有 json 对象的简单数组

这是我的代码

Startup.cs

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

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {               
            //connection avec MySql in the new projetc 
            var connectionString = Configuration.GetConnectionString("DefaultConnection");
            services.AddDbContext<ApplicationDbContext>(options =>
            options.UseMySql(connectionString, new MySqlServerVersion(new Version(8, 0, 19)), mySqlOptions => mySqlOptions.CharSetBehavior(CharSetBehavior.NeverAppend)));

            services.AddDbContext<ApplicationDbContext>(opt => opt.UseInMemoryDatabase("commande_clt"));
            services.AddControllers().AddOData(opt => opt.AddRouteComponents("odata", GetEdmModel()));         // Odata
            
            services.AddScoped<ITransaction, Transaction>();
            services.AddScoped<ICommandeClientServices, CommandeClientServices>();
            services.AddScoped<IArticleServices, ArticleServices>();
            services.AddScoped(typeof(IAppLogger), typeof(LoggerAdapter));
            services.AddScoped<IWebUserServices, WebUserServices>();
      
            services.AddTransient(typeof(IGenericRepository<>), typeof(GenericRepository<>));
            services.AddTransient(typeof(IGenericRepositoryReadOnly<>), typeof(GenericRepositoryReadOnly<>));
          
            services.AddScoped<IStocksDepotServices, StocksDepotServices>();
            services.AddScoped<IClientsServices, ClientsServices>();

            services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("CommandeOpenApi",
                    new OpenApiInfo
                    {
                        Title = "Commande Client",
                        Description = "Développé par HTSoft",
                        Version = "1"
                    });
            });

            var appSettingsSection = Configuration.GetSection("AppSettings");
            services.Configure<AppSettings>(appSettingsSection);
            var appSettings = appSettingsSection.Get<AppSettings>();
            var key = Encoding.ASCII.GetBytes(appSettings.secret);
            CommandeClientCleanArch.ApplicationCore.AppSettings.secret2 = appSettings.secret;
            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
                .AddJwtBearer(x =>
                {
                    x.RequireHttpsMetadata = false;
                    x.SaveToken = true;
                    x.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuerSigningKey = true,

                        IssuerSigningKey = new SymmetricSecurityKey(key),
                        ValidateIssuer = false, //lors du déploiyement cette variable doit etre true
                        ValidateAudience = false //lors du déploiyement cette variable doit etre true
                    };
                });

            services.AddSwaggerGen(setup =>
            {
                // Include 'SecurityScheme' to use JWT Authentication
                var jwtSecurityScheme = new OpenApiSecurityScheme
                {
                    Scheme = "bearer",
                    BearerFormat = "JWT",
                    Name = "JWT Authentication",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.Http,
                    Description = "Put **_ONLY_** your JWT Bearer token on textbox below!",

                    Reference = new OpenApiReference
                    {
                        Id = JwtBearerDefaults.AuthenticationScheme,
                        Type = ReferenceType.SecurityScheme
                    }
                };
                setup.SwaggerDoc("v1", new OpenApiInfo { Title = "MyTestService", Version = "v1", });
                setup.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
                setup.AddSecurityDefinition(jwtSecurityScheme.Reference.Id, jwtSecurityScheme);
                setup.AddSecurityRequirement(new OpenApiSecurityRequirement()
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id="Bearer"
                            },
                            Scheme="oauth2",
                            Name="Bearer",
                            In = ParameterLocation.Header,
                        },
                        new List<String>()
                    }
                });
            });

            services.AddRouting();
          
            services.AddCors(options =>
            {
                options.AddPolicy("AllowAnyCorsPolicy", policy => policy.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin());
            });

            services.AddHttpClient();
            services.AddControllers();
        }

        // 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())
            {
                AppSettings.IsDevelopment = true;
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebApi v1"));
            }
            else
            {
                AppSettings.IsDevelopment = false;
            }
            app.UseDeveloperExceptionPage();
            app.UseHttpsRedirection();

            app.UseRouting();
            app.UseCors("AllowAnyCorsPolicy");
            app.UseAuthorization();
    
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

        private static IEdmModel GetEdmModel()
        {
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
            builder.EntitySet<CommandeClt>("commande_clt");
            return builder.GetEdmModel();
        }
    }
}

CommandeClientController.cs { [路由(“api/[控制器]”)] [EnableCors("AllowAnyCorsPolicy")] [ApiController]

    //[Authorize]
   
    public class CommandeClientController : ODataController
    {
        private readonly ICommandeClientServices _CommandeClientServices;
      //  private readonly IArticleServices _discountPromotionServices;

        public CommandeClientController(ICommandeClientServices CommandeClientService ,IArticleServices discountPromotionServices)
        {
            _CommandeClientServices = CommandeClientService;
       //     _discountPromotionServices = discountPromotionServices;

        }
       
        [HttpPost("AjoutArticle")]
        //[Authorize(Roles = "User, Admin")]

        public IActionResult AjouterArticleCommande([FromBody] ArticleCommande a)
        {
            try
            {
                ArticleCommande unar = new ArticleCommande();
                unar.cod_art = "00-";
                
                unar.qte_cde = 4;
                unar.num_cde_clt = "BC BB 0018/21";
                

                if (unar.qte_cde <= 0)
                {
                    throw new Exception("Erreur Saisie Quantité Ajoutée");
                }
                CommandeClt articleAjouté = _CommandeClientServices.AddArticle(unar);
                _CommandeClientServices.Commit();
                return Ok(articleAjouté);
            }
            catch (Exception ex)
            {
                ModelState.AddModelError("Erreur Create Commande client Controller 11032021", $"{ex.Message}");
                return BadRequest(ex.Message);
            }
        }
    
        [HttpPost("SuppressionArticle")]
        //[Authorize(Roles = "User, Admin")]
        public IActionResult DeleteCommandeArticle([FromBody] ArticleCommande a)
        {
            try
            {
                CommandeClt articleSupprimer = _CommandeClientServices.RemoveArticle(a);
                _CommandeClientServices.Commit();
                return Ok(articleSupprimer);
            }
            catch (Exception ex)
            {
                ModelState.AddModelError("Erreur Create Commande client Controller 11032021", $"{ex.Message}");
                return BadRequest(ex.Message);
            }
        }
        
        [HttpPatch("UpdateArticle")]
        public IActionResult UpdateCommandeArticle([FromBody] ArticleCommande a)
        {
            try
            {
                CommandeClt articlemodifier = _CommandeClientServices.UpdateArticle(a);
                _CommandeClientServices.Commit();
                return Ok(articlemodifier);
        }
            catch (Exception ex)
            {
                ModelState.AddModelError("Erreur Update Commande client Controller 11032021", $"{ex.Message}");
                return BadRequest(ex.Message);
    }
}
        [HttpPatch("UpdateCommande")]
        public IActionResult UpdateCommande([FromBody] CommandeClt commande)
        {
            try
            { 
                CommandeClt commandeModifer = _CommandeClientServices.UpdateCommande(commande);
                _CommandeClientServices.Commit();
                return Ok(commandeModifer);
            }
            catch (Exception ex)
            {
                ModelState.AddModelError("Erreur Create Commande client Controller 11032021", $"{ex.Message}");
                return BadRequest(ex.Message);
            }


        }
        
        [HttpPost("Create")]
        //[Authorize(Roles = "Admin")]
        public IActionResult CreateCommande([FromBody] CommandeClt cmd)
        {
            try
            {
                _CommandeClientServices.BeginTransaction();

                CommandeClt c1 = new CommandeClt();
                c1 = new CommandeClt();
                c1.cod_clt = "4119351";
                c1.rais_soc_clt = "ADRF";
                c1.articles = new List<ArticleCommande>();
               
                


                if (cmd.cod_clt == null || cmd.cod_clt.Trim() == "")
                {
                    throw new Exception("Code Client est trés important ");
                }

                if (!ModelState.IsValid)
                {
                    return BadRequest(ModelState);
                }
                CommandeClt commande = _CommandeClientServices.Create(c1);
                if (commande == null)
                {
                    ModelState.AddModelError("", $"Erreur de creation du commande 20210312");
                    return StatusCode(500, ModelState);
                }
                _CommandeClientServices.Commit();
                return Ok("Votre commande "+ commande.num_cde_clt+ " est créée avec succès");

            }

            catch (Exception ex)
            {
                ModelState.AddModelError("Erreur Create Commande client Controller 11032021", $"{ex.Message}");
                return BadRequest(ex.Message);
            }
            

        }

        /// <summary>
        /// Recupérer toutes les commandes, Cet API n'est authorisé que par l'administareur
        /// </summary>
        /// <returns></returns>


        /// <summary>
        /// Cet API permet de recupérer tout les commande du client, De plus on peux filtré ses commandes soit par dates ou par etats
       
      
        [HttpGet]
        [EnableQuery]
        //[Authorize(Roles = "User

        public  IActionResult GetCommandes(string codclt, DateTime datedebut, DateTime datefin , string etat = "")
        {
            try
            {

                codclt = "4119351";
                datedebut = new DateTime(2021, 7, 1);
                datefin = new DateTime(2021, 7, 20);
                //les variable de type DateTime ne jamais soient null !
                // pour dire que les date sont nul alors il faut qui il soient egaux à 01 / 01 / 0001
                if (codclt == null || codclt.Trim()=="")
                {
                    throw new Exception("Code client est obligatoire");
                }
                if(datefin < datedebut)
                {
                    throw new Exception("Date Fin doit etre superieur a date Debut");
                }
                IQueryable<CommandeClt> CommandesFiltrees =  _CommandeClientServices.GetCommandes(codclt, datedebut, datefin, etat);
               // if (CommandesFiltrees==null)
                {
               //     return Ok("Pas de Commande pour ce Client");
                }
                return  Ok(CommandesFiltrees);
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("Erreur GetCommandes Commande client Controller 15032021", $"{ex.Message}");
                return BadRequest(ex.Message);
            }
        }
       
        /// <summary>
        /// Cet API est pour le le client WEB, ICI on Créé une commande que si le client ne possède pas une commande déja créée!! 
        /// </summary>
        /// <param name="commande"></param>
        /// <returns></returns>
        [HttpPost("GetLastOrCreate")]
        //[Authorize(Roles = "User")]
        public IActionResult GetLastOrCreate([FromBody] CommandeClt commande)
        {
            try
            {
                if (commande.cod_clt == null || commande.cod_clt.Trim() == "")
                {
                    throw new Exception("Code Client est trés important !");
                }
                if (!ModelState.IsValid)
                {
                    return BadRequest(ModelState);
                }
                CommandeClt getLastOrCreate = _CommandeClientServices.GetLastOrCreate(commande);
                if (getLastOrCreate == null)
                {
                    ModelState.AddModelError("", $"erreur de creation du commande 20210314");
                    return StatusCode(500, ModelState);
                }
                return Ok(getLastOrCreate);
            }
            catch (Exception ex)
            {
                ModelState.AddModelError("Erreur GetLastOrCerate Commande client Controller 11032021", $"{ex.Message}");
                return BadRequest(ex.Message);
            }
        }

    
        
        /// <summary>
        /// Cet API Permet d'Annuler une CommandeClient
        /// </summary>
        /// <param name="num_cde_clt"></param>
        /// <returns></returns>
        [HttpPatch("AnnulerCommande")]
        public IActionResult AnnulerCommande(string num_cde_clt)
        {
            try
            {
                if (num_cde_clt == null)
                {
                    throw new Exception("Vous devez saisie le num_cde_clt");
                }
                Boolean annulation = _CommandeClientServices.CancelCommande(num_cde_clt);
                if (annulation == false)
                {
                    return BadRequest("l'annulation n'est pas effectuée! La Commande est deja Annulée");
                }
                _CommandeClientServices.Commit();
                return Ok("Commande est annulée");

            }
            catch (Exception ex)
            {
                ModelState.AddModelError("Erreur Annulation Commande client Controller 18032021", $"{ex.Message}");
                return BadRequest(ex.Message);
            }
        }
        /// <summary>
        /// Cet API permet de supprimer une CommandeClient , et donc supprimer tous les articles ajoutée a cette CommandeClient
        /// </summary>
        /// <param name="num_cde_clt"></param>
        /// <returns></returns>
        [HttpDelete("SupprimerCommande")]
        public IActionResult DeleteCommande(string num_cde_clt)
        {
            try
            {
                //throw new Exception("Acces refusé");
                //if(num_cde_clt== null || num_cde_clt.Trim() == "")
                //{
                //    throw new Exception("Vous devez indiquer la commande à supprimer");
                //}
                //Boolean suppression = _CommandeClientServices.DeleteCommande(num_cde_clt);
                //if (suppression == false)
                //{
                //    return BadRequest("la suppression n'est pas effectuée! cette commande n'existe pas");
                //}
                return Ok("Pas encore implémentée");
            }
            catch (Exception ex)
            {
                ModelState.AddModelError("Erreur suppression Commande client Controller 21032021", $"{ex.Message}");
                return BadRequest(ex.Message);
            }
        }




    }




}

ComandeClt.cs 模型

{
    public partial class CommandeClt
    {
       
        [Key]
        public string num_cde_clt { get; set; }
        [Required(ErrorMessage ="code client est obligatoire")]
        public string cod_clt { get; set; }
        public string rais_soc_clt { get; set; }
        public string etat_cde { get; set; }
        public DateTime dat_cde { get; set; }
        public decimal totalht { get; set; }
        public decimal tva { get; set; }
        public decimal totalttc { get; set; }
        public string transporteur { get; set; }
        public string adresse { get; set; }
        public string societe { get; set; }
        [JsonIgnore]
        public TimeSpan time_cde { get; set; }
        public decimal net { get; set; }
        public decimal remise { get; set; }
        [JsonIgnore]
        public decimal fodec { get; set; }
        [JsonIgnore]
        public string username { get; set; }
        public DateTime dat_liv { get; set; }
        [JsonIgnore]
        public string typec { get; set; }
        [JsonIgnore]
        public string typeexport { get; set; }
        public ICollection<ArticleCommande> articles { get; set; }
        public string cod_dep { get; set; }
        public CommandeClt()
        {
            fodec = 0;
            remise = 0;
            totalht = 0;
            tva = 0;
            totalttc = 0;
            net = 0;

        }
        public CommandeClt(string cod_clt)
        {
            this.cod_clt = cod_clt;

        }


    }
    }

ApplicationDbContext.cs

{
    public class ApplicationDbContext : DbContext
    {
        public string societe { get; set; }
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
        {
            try
            {
                System.IO.StreamWriter sr1 = new System.IO.StreamWriter("newApplicationDbContext.txt", true);
                sr1.WriteLine(DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());
                sr1.Close();
            }
            catch (Exception)
        {

            ;
        }
        
    }
    // ses deux tables pour l'authentification
    public DbSet<WebUserModel> web_users { get; set; }
    public DbSet<Wemdev> web_usersspec { get; set; }
    // c'est le table des commandes 
    public DbSet<CommandeClt> commande_clt { get; set; }
    // c'est le table de articles ajouter a une commande 
    public DbSet<ArticleCommande> article_commande_clt { get; set; }
    public DbSet<Article> article { get; set; }
    public DbSet<Client> client { get; set; }
    public DbSet<RemisePeriode> remise_periode { get; set; }
    public DbSet<StockDepot> article_depot { get; set; }
    public DbSet<Depot> depot { get; set; }
    public DbSet<ArticleVoitures> article_marquesvoit { get; set; }
    public DbSet<ArticleFamille> famille_article { get; set; }  
    public DbSet<ArticleFamilleParent> famille_article_p { get; set; }
    public DbSet<ArticlePhoto> article_photo { get; set; }
    public DbSet<ArticleMarque> marq_article { get; set; }
    public DbSet<ArticleCategorie> cat_article { get; set; }
    public DbSet<Historique> historique { get; set; }
    public DbSet<Parametresf> parametresf { get; set; }
    public DbSet<Parametres2> parametres { get; set; }
    public DbSet<Synchrodeletes> synchro_deletes { get; set; }
    public DbSet<Tables> tables { get; set; }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {

            optionsBuilder.UseMySql("server=localhost;user id=root;port=3307;database=htsoft;password=htsoft14789;persistsecurityinfo=True", 
                new MySqlServerVersion(new Version(8, 0, 19)),
                mySqlOptions => mySqlOptions.CharSetBehavior(CharSetBehavior.NeverAppend));

        }
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {

        //c'est une facon pour créee les navigation et les jointure

       // Database.BeginTransaction();
        // 1 to many , chaque article possède plusieur remise 
        modelBuilder.Entity<RemisePeriode>()
            .HasOne(a => a.articles).WithMany(r => r.remiseArticle)
            .HasForeignKey(a=>a.cod_art);
        //ICI on a crée une navigation de la class article a la class Remise periode 
        modelBuilder.Entity<Article>()
        .Navigation(r => r.remiseArticle)
        .UsePropertyAccessMode(PropertyAccessMode.Property);




        modelBuilder.Entity<ArticlePhoto>()
           .HasOne(a => a.articles).WithOne(r => r.photo)
           .HasForeignKey<ArticlePhoto>(e => e.cod_art);
        modelBuilder.Entity<Article>()
            .Navigation(r => r.photo)
            .UsePropertyAccessMode(PropertyAccessMode.Property);


        modelBuilder.Entity<ArticleCommande>()
            .HasOne(a => a.commande).WithMany(r => r.articles)
            .HasForeignKey(a => a.num_cde_clt);
        //ICI on a crée une navigation de la class article a la class Remise periode 
        //.HasQueryFilter(p => p.dat_cde.Year == DateTime.Today.Year && p.dat_cde.Month == DateTime.Today.Month)
        modelBuilder.Entity<CommandeClt>()
        .Navigation(r => r.articles)
        .UsePropertyAccessMode(PropertyAccessMode.Property);

        modelBuilder.Entity<Historique>()
        .HasQueryFilter(p => 1 == 2);
        //modelBuilder.Entity<Historique>()
        //.Navigation(r => r.cod)
        //.UsePropertyAccessMode(PropertyAccessMode.Property);
        

    }
    public object GetPropValue(object src, string propName)
    {
        return src.GetType().GetProperty(propName).GetValue(src, null) == null ? DBNull.Value : src.GetType().GetProperty(propName).GetValue(src, null);
    }


    
  public  object GetParametre(int numtableparam, string nom_param)
    {


        if (numtableparam == 1)
        {
            IQueryable<Parametresf> lis = parametresf.Where(condition => condition.societe == societe);
            Parametresf obje = lis.FirstOrDefault<Parametresf>();

            if (obje == null)
                throw new Exception("Aucune ligne dans parametresf pour la societe:" + societe);
            //foreach (var prop in obje.GetType().GetProperties())


            //if (prop.Name == nom_param)
            return GetPropValue(obje, nom_param);



        }
        if (numtableparam == 2)
        {
            IQueryable<Parametres2> lis2 = parametres.Where(condition => condition.societe == societe);
            Parametres2 obje = lis2.FirstOrDefault<Parametres2>();

            if (obje == null)
                throw new Exception("Aucune ligne dans parametres pour la societe:" + societe);

            return GetPropValue(obje, nom_param);

        }

        return DBNull.Value;
    }
}
}

这是我招摇界面的一些截图: swagger/metadata swagger/odata

这是我的依赖列表: Dependecies

【问题讨论】:

  • 您好,我想您可以在 startup.cs 的 GetEdmModel() 方法中将值 commande_clt 更改为 CommandeClient。并且您需要将控制器中的路由属性更改为[Route("odata/[controller]")],就像您在启动时设置的那样。详情已在下方更新。
  • 简单来说就是AddRouteComponents中的设置提醒了odata控制器的前缀路径,并且EdmModel名称要与odata控制器名称保持一致。
  • 先生有什么流程吗?如果存在,请分享您的进一步问题。如果您觉得我的帖子对您​​有帮助,您能接受它作为答案吗?
  • 非常感谢@TinyWang 的帮助
  • 没关系,我很高兴看到它对你有用 :)

标签: c# asp.net-core


【解决方案1】:

我发现错误,它来自odata v8的routing rule

端点与OData关系的构建 路由模板是基于一组规则的,这样的规则称为 OData 路由约定。例如,“CustomersController”是一个 控制器名称“客户”是实体集时的 OData 控制器 在给定的 Edm 模型中。 “EntitySetName + Controller”是OData之一 控制器名称约定。

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

private static IEdmModel GetEdmModel()
        {
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
            builder.EntitySet<LocalMallUser>("Users");
            return builder.GetEdmModel();
        }

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

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.OData.Query;
using Microsoft.AspNetCore.OData.Routing.Controllers;
using WebApi2.Data;

namespace WebApi.Controllers
{
    [Route("odata/[Controller]")]
    public class UsersController : ODataController
    {
        private readonly LocaldbContext _context;

        public UsersController(LocaldbContext context)
        {
            _context = context;
        }

        [EnableQuery]
        public IActionResult Get()
        {
            return Ok(_context.user);
        }
    }
}

ConfigureServices在启动时,AddRouteComponents确定路由前缀:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<LocaldbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("Localtest")));
            services.AddControllers().AddOData(opt => opt.EnableQueryFeatures().AddRouteComponents("odata",GetEdmModel()));
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApi2", Version = "v1" });
            });
            //services.AddOData();
        }

【讨论】:

  • 谢谢,但我需要响应为 Odata 类型,以便我可以在 devExpress 组件中实现它,如下所示:@Odata.context.......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-05
  • 2021-12-14
  • 1970-01-01
  • 1970-01-01
  • 2023-02-22
  • 1970-01-01
  • 2013-02-23
相关资源
最近更新 更多