Blazor Button Not Saving Data to Database in EF Core

I want to my button “Votar” insert data of vote in table of my database “Votes”, but when i click in the button nothing happens, doesn’t show any error or something like this.
My structure of code are there, can we help me?

DBLayer
namespace ESOF.WebApp.DBLayer.Context;

using ESOF.WebApp.DBLayer.Entities;
using Microsoft.EntityFrameworkCore;

public partial class ApplicationDbContext{
    private void BuildGames(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Game>()
            .HasKey(g => g.GameId);
            
        modelBuilder.Entity<Game>()
            .Property(g => g.GameId)
            .HasDefaultValueSql("gen_random_uuid()");

        
        modelBuilder.Entity<Game>()
            .Property(g => g.Name)
            .IsRequired();
        
        modelBuilder.Entity<Game>()
            .Property(g => g.Description)
            .IsRequired();
    }
}


using ESOF.WebApp.DBLayer.Entities;
using Microsoft.EntityFrameworkCore;

// ReSharper disable once CheckNamespace
namespace ESOF.WebApp.DBLayer.Context;

public partial class ApplicationDbContext
{
    private void BuildPermissions(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Permission>()
            .HasMany(p => p.RolePermissions)
            .WithOne(rp => rp.Permission)
            .HasForeignKey(rp => rp.PermissionId);
        
        modelBuilder.Entity<Permission>()
            .Property(p => p.PermissionId)
            .HasDefaultValueSql("gen_random_uuid()");
    }
}


using ESOF.WebApp.DBLayer.Entities;
using Microsoft.EntityFrameworkCore;

// ReSharper disable once CheckNamespace
namespace ESOF.WebApp.DBLayer.Context;
public partial class ApplicationDbContext
{
    private void BuildRolePermissions(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<RolePermission>()
            .HasKey(e => new { e.RoleId, e.PermissionId });

    }
}


using ESOF.WebApp.DBLayer.Entities;
using Microsoft.EntityFrameworkCore;

// ReSharper disable once CheckNamespace
namespace ESOF.WebApp.DBLayer.Context;

public partial class ApplicationDbContext
{
    private void BuildRoles(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Role>()
            .HasMany(r => r.UserRoles)
            .WithOne(ur => ur.Role)
            .HasForeignKey(ur => ur.RoleId);

        modelBuilder.Entity<Role>()
            .HasMany(r => r.RolePermissions)
            .WithOne(rp => rp.Role)
            .HasForeignKey(rp => rp.RoleId);
        
        modelBuilder.Entity<Role>()
            .Property(p => p.RoleId)
            .HasDefaultValueSql("gen_random_uuid()");
    }
}


using ESOF.WebApp.DBLayer.Entities;
using Microsoft.EntityFrameworkCore;

// ReSharper disable once CheckNamespace
namespace ESOF.WebApp.DBLayer.Context;

public partial class ApplicationDbContext
{
    private void BuildUserRoles(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<UserRole>()
            .HasKey(e => new { e.RoleId, e.UserId });

    }
}


using ESOF.WebApp.DBLayer.Entities;
using Microsoft.EntityFrameworkCore;

// ReSharper disable once CheckNamespace
namespace ESOF.WebApp.DBLayer.Context;

public partial class ApplicationDbContext
{
    private void BuildUsers(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>()
            .HasMany(u => u.UserRoles)
            .WithOne(ur => ur.User)
            .HasForeignKey(ur => ur.UserId);

        modelBuilder.Entity<User>()
            .HasIndex(u => u.Email)
            .IsUnique();
        
        modelBuilder.Entity<User>()
            .Property(p => p.UserId)
            .HasDefaultValueSql("gen_random_uuid()");
    }
}


using ESOF.WebApp.DBLayer.Entities;
using Microsoft.EntityFrameworkCore;

namespace ESOF.WebApp.DBLayer.Context;

public partial class ApplicationDbContext{
    private void BuildVotes(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Vote>()
            .HasKey(e => e.VoteId);

        modelBuilder.Entity<Vote>()
            .Property(v => v.VoteId)
            .HasDefaultValueSql("gen_random_uuid()");

        modelBuilder.Entity<Vote>()
            .Property(v => v.VoteTime)
            .IsRequired();

        modelBuilder.Entity<Vote>()
            .Property(v => v.UserId)
            .IsRequired();
        
        modelBuilder.Entity<Vote>()
            .Property(v => v.GameId)
            .IsRequired();

        modelBuilder.Entity<Vote>()
            .HasOne(e => e.User)
            .WithMany(u => u.Votes)
            .HasForeignKey(e => e.UserId)
            .HasConstraintName("id_user__fk");

        modelBuilder.Entity<Vote>()
            .HasOne(e => e.Game)
            .WithMany(g => g.Votes)
            .HasForeignKey(e => e.GameId)
            .HasConstraintName("id_game__fk");
    }
}


using DotNetEnv;
using ESOF.WebApp.DBLayer.Entities;
using Helpers;
using Microsoft.EntityFrameworkCore;

namespace ESOF.WebApp.DBLayer.Context;

public partial class ApplicationDbContext : DbContext
{
    private static readonly DbContextOptions DefaultOptions = new Func<DbContextOptions>(() =>
    {
        var optionsBuilder = new DbContextOptionsBuilder();
        var db = EnvFileHelper.GetString("POSTGRES_DB");
        var user = EnvFileHelper.GetString("POSTGRES_USER");
        var password = EnvFileHelper.GetString("POSTGRES_PASSWORD");
        var port = EnvFileHelper.GetString("POSTGRES_PORT");
        var host = EnvFileHelper.GetString("POSTGRES_HOST");

        if (string.IsNullOrEmpty(db) || string.IsNullOrEmpty(user) || string.IsNullOrEmpty(password) ||
            string.IsNullOrEmpty(port) || string.IsNullOrEmpty(host))
        {
            throw new InvalidOperationException(
                "Database connection information not fully specified in environment variables.");
        }

        var connectionString = $"Host={host};Port={port};Database={db};Username={user};Password={password}";
        optionsBuilder.UseNpgsql(connectionString);
        return optionsBuilder.Options;
    })();
    
    public ApplicationDbContext()
        : base(DefaultOptions)
    {
    }

    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }
    
    public DbSet<User> Users { get; set; }
    public DbSet<Role> Roles { get; set; }
    public DbSet<Permission> Permissions { get; set; }
    public DbSet<UserRole> UserRoles { get; set; }
    public DbSet<RolePermission> RolePermissions { get; set; }
    public DbSet<Game> Games { get; set; }
    public DbSet<Vote> Votes { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);


    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        BuildUsers(modelBuilder);
        BuildRoles(modelBuilder);
        BuildPermissions(modelBuilder);
        BuildRolePermissions(modelBuilder);
        BuildUserRoles(modelBuilder);
        BuildGames(modelBuilder); 
        BuildVotes(modelBuilder);
        base.OnModelCreating(modelBuilder);
        
    }
}


using System.ComponentModel.DataAnnotations;

namespace ESOF.WebApp.DBLayer.Entities;

public class Game{
    [Key]
    public Guid GameId{ get; set; }
    
    [Required]
    public String Name{ get; set; }
    
    [Required]
    public String Description{ get; set; }
    
    public ICollection<Vote> Votes { get; set; }
}


using System.ComponentModel.DataAnnotations;

namespace ESOF.WebApp.DBLayer.Entities;

public class Permission
{
    [Key]
    public Guid PermissionId { get; set; }
    
    [Required]
    public string Name { get; set; }
    public ICollection<RolePermission> RolePermissions { get; set; }
}


using System.ComponentModel.DataAnnotations;

namespace ESOF.WebApp.DBLayer.Entities;

public class Role
{
    [Key]
    public Guid RoleId { get; set; }
    
    [Required]
    public string Name { get; set; }
    public ICollection<UserRole> UserRoles { get; set; }
    public ICollection<RolePermission> RolePermissions { get; set; }
}


using System.ComponentModel.DataAnnotations;

namespace ESOF.WebApp.DBLayer.Entities;

public class RolePermission
{
    public Guid RoleId { get; set; }
    
    public Guid PermissionId { get; set; }
    
    public Role Role { get; set; }
    public Permission Permission { get; set; }
}


using System.ComponentModel.DataAnnotations;

namespace ESOF.WebApp.DBLayer.Entities;

public class User
{
    [Key]
    public Guid UserId { get; set; }
    
    [EmailAddress, Required]
    public string Email { get; set; }
    
    [Required]
    public byte[] PasswordHash { get; set; }
    
    [Required]
    public byte[] PasswordSalt { get; set; }
    public ICollection<UserRole> UserRoles { get; set; }
    
    public ICollection<Vote> Votes { get; set; }
}


namespace ESOF.WebApp.DBLayer.Entities;

public class UserRole
{
    public Guid UserId { get; set; }
    public User User { get; set; }
    public Guid RoleId { get; set; }
    public Role Role { get; set; }
}


using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ESOF.WebApp.DBLayer.Entities;

public class Vote
{
    [Key]
    public Guid VoteId { get; set; }
    
    [Required]
    public Guid UserId { get; set; }
    
    [ForeignKey(nameof(UserId))]
    public User User { get; set; }
    
    [Required]
    public Guid GameId { get; set; }
    
    [ForeignKey(nameof(GameId))]
    public Game Game { get; set; }
    
    [Required]
    public DateTime VoteTime { get; set; }
}



Frontend
@page "/gameofthemonth"
@using ESOF.WebApp.DBLayer.Entities
@inject HttpClient Http

<h3>Vote no Jogo do Mês</h3>

@if (games == null)
{
    <p>Carregando...</p>
}
else if (!games.Any())
{
    <p>Nenhum jogo encontrado.</p>
}
else
{
    <ul>
        @foreach (var game in games)
        {
            <li>
                <b>@game.Name</b> - @game.Description
                <button @onclick="@(async () => await VoteForGame(userId, game.GameId))" disabled="@hasVoted">Votar</button>

                @if (votePercentages.TryGetValue(game.GameId, out var percentage))
                {
                    <span>(@percentage%)</span>
                }
            </li>
        }
    </ul>
}

<p>@message</p>

@code {
    private List<Game>? games;
    private string? message;
    private Guid userId = Guid.NewGuid();
    private bool hasVoted = false;
    private Dictionary<Guid, double> votePercentages = new();
    private bool isVotingPeriod = false;

    protected override async Task OnInitializedAsync()
    {
        try
        {
            games = await Http.GetFromJsonAsync<List<Game>>("api/game");
            hasVoted = await CheckIfUserHasVoted();
            isVotingPeriod = IsVotingPeriod();
            if (games == null)
            {
                message = "Nenhum jogo foi retornado da API.";
            }
            else
            {
                await UpdateVotePercentages();
            }
        }
        catch (Exception ex)
        {
            message = "Erro ao carregar os jogos: " + ex.Message;
        }
    }

    private bool IsVotingPeriod()
    {
        var today = DateTime.Now;
        var lastDayOfMonth = new DateTime(today.Year, today.Month, DateTime.DaysInMonth(today.Year, today.Month));
        var firstVotingDay = lastDayOfMonth.AddDays(-4);
        return today >= firstVotingDay;
    }

    private async Task<bool> CheckIfUserHasVoted()
    {
        return await Http.GetFromJsonAsync<bool>($"api/vote/HasVoted/{userId}");
    }

    private async Task VoteForGame(Guid userId, Guid gameId)
    {
        if (!isVotingPeriod)
        {
            message = "A votação só está disponível nos últimos 5 dias do mês.";
            return;
        }

        try
        {
            if (await CheckIfUserHasVoted())
            {
                message = "Você já votou neste mês.";
                return;
            }

            var vote = new Vote { UserId = userId, GameId = gameId, VoteTime = DateTime.Now };
            var response = await Http.PostAsJsonAsync("api/vote", vote);

            if (response.IsSuccessStatusCode)
            {
                message = "Voto registrado com sucesso!";
                hasVoted = true;
                await UpdateVotePercentages();
            }
            else
            {
                var errorContent = await response.Content.ReadAsStringAsync();
                message = errorContent.Contains("Já votou este mês.") ? "Já votou este mês." : "Erro ao registrar voto.";
            }
        }
        catch (Exception ex)
        {
            message = "Erro ao tentar registrar o voto: " + ex.Message;
        }

        StateHasChanged();
    }

    private async Task UpdateVotePercentages()
    {
        var voteCounts = await Http.GetFromJsonAsync<Dictionary<Guid, int>>("api/vote/Counts");
        if (voteCounts != null)
        {
            var totalVotes = voteCounts.Values.Sum();
            foreach (var game in games)
            {
                votePercentages[game.GameId] = voteCounts.TryGetValue(game.GameId, out var count) ? (double)count / totalVotes * 100 : 0;
            }
        }
    }
}



@page "/votes"
@inject HttpClient Http
@using ESOF.WebApp.DBLayer.Entities

<h3>Jogo do Mês</h3>

@if (gameOfTheMonth != null)
{
    <div>
        <b>@gameOfTheMonth.Name</b>
        <p>@gameOfTheMonth.Description</p>
    </div>
}
else
{
    <p>Nenhum jogo foi selecionado este mês.</p>
}

@code {
    private Game? gameOfTheMonth;

    protected override async Task OnInitializedAsync()
    {
        try
        {
            gameOfTheMonth = await Http.GetFromJsonAsync<Game>("api/vote/GameOfTheMonth");
        }
        catch (Exception ex)
        {
            Console.WriteLine("Erro ao carregar o jogo do mês: " + ex.Message);
        }
    }
}


namespace Frontend.Helpers;

public class ApiHelper(HttpClient httpClient)
{
    public async Task<T?> GetFromApiAsync<T>(string url)
    {
        try
        {
            var response = await httpClient.GetAsync(url);
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadFromJsonAsync<T>();
        }
        catch (HttpRequestException e)
        {
            // Handle exception
            throw new ApplicationException($"Error fetching data from {url}: {e.Message}");
        }
    }
}


using ESOF.WebApp.DBLayer.Entities;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;
using System.Collections.Generic;

namespace Frontend.Services
{
    public class VoteService
    {
        private readonly HttpClient _httpClient;

        public VoteService(HttpClient httpClient)
        {
            _httpClient = httpClient;
        }

        public async Task<List<Game>> GetGamesAsync()
        {
            return await _httpClient.GetFromJsonAsync<List<Game>>("api/game");
        }

        public async Task<bool> HasUserVotedAsync(Guid userId)
        {
            return await _httpClient.GetFromJsonAsync<bool>($"api/vote/HasVoted/{userId}");
        }

        public async Task<HttpResponseMessage> VoteForGameAsync(Vote vote)
        {
            return await _httpClient.PostAsJsonAsync("api/vote", vote);
        }

        public async Task<Dictionary<Guid, int>> GetVoteCountsAsync()
        {
            return await _httpClient.GetFromJsonAsync<Dictionary<Guid, int>>("api/vote/Counts");
        }
    }
}

WebAPI
using Microsoft.AspNetCore.Mvc;
using ESOF.WebApp.DBLayer.Entities;
using ESOF.WebApp.DBLayer.Context;
using Microsoft.EntityFrameworkCore;

[Route("api/[controller]")]
[ApiController]
public class GameController : ControllerBase
{
    private readonly ApplicationDbContext _context;

    public GameController(ApplicationDbContext context)
    {
        _context = context;
    }

    [HttpGet]
    public async Task<ActionResult<IEnumerable<Game>>> GetGames()
    {
        try
        {
            var games = await _context.Games.ToListAsync();
            return Ok(games);
        }
        catch (Exception ex)
        {
            // Log exception
            Console.WriteLine($"Erro ao buscar jogos: {ex.Message}");
            return StatusCode(500, "Erro interno no servidor.");
        }
    }

    [HttpGet("{id}")]
    public async Task<ActionResult<Game>> GetGame(Guid id)
    {
        try
        {
            var game = await _context.Games.FindAsync(id);

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

            return game;
        }
        catch (Exception ex)
        {
            // Log exception
            Console.WriteLine($"Erro ao procurar jogo: {ex.Message}");
            return StatusCode(500, "Erro interno no servidor.");
        }
    }
}


using Microsoft.AspNetCore.Mvc;
using System;
using System.Linq;
using System.Threading.Tasks;
using ESOF.WebApp.DBLayer.Context;
using ESOF.WebApp.DBLayer.Entities;
using Microsoft.EntityFrameworkCore;

[Route("api/[controller]")]
[ApiController]
public class VoteController : ControllerBase
{
    private readonly ApplicationDbContext _context;

    public VoteController(ApplicationDbContext context)
    {
        _context = context;
    }

    [HttpPost]
    public async Task<IActionResult> Vote([FromBody] Vote vote)
    {
        var today = DateTime.Now;
        var lastDayOfMonth = new DateTime(today.Year, today.Month, DateTime.DaysInMonth(today.Year, today.Month));
        var firstVotingDay = lastDayOfMonth.AddDays(-4);

        if (today < firstVotingDay)
        {
            return BadRequest("A votação só está disponível nos últimos 5 dias do mês.");
        }

        try
        {
            var existingVote = await _context.Votes
                .FirstOrDefaultAsync(v => v.UserId == vote.UserId && 
                                          v.VoteTime.Month == today.Month && 
                                          v.VoteTime.Year == today.Year);

            if (existingVote != null)
            {
                return BadRequest("Você já votou este mês.");
            }

            vote.VoteTime = today;
            _context.Votes.Add(vote);
            await _context.SaveChangesAsync();

            return Ok();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Erro ao registrar voto: {ex.Message}");
            return StatusCode(500, "Erro interno no servidor.");
        }
    }
    
    [HttpGet("GameOfTheMonth")]
    public async Task<ActionResult<Game>> GetGameOfTheMonth()
    {
        try
        {
            var gameOfTheMonthId = await _context.Votes
                .Where(v => v.VoteTime.Month == DateTime.Now.Month && v.VoteTime.Year == DateTime.Now.Year)
                .GroupBy(v => v.GameId)
                .OrderByDescending(g => g.Count())
                .Select(g => g.Key)
                .FirstOrDefaultAsync();

            if (gameOfTheMonthId == default)
            {
                return NotFound("Nenhum voto foi registado este mês.");
            }

            var game = await _context.Games.FindAsync(gameOfTheMonthId);
            return Ok(game);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Erro ao procurar jogo do mês: {ex.Message}");
            return StatusCode(500, "Erro interno no servidor.");
        }
    }



    [HttpGet("HasVoted/{userId}")]
    public async Task<ActionResult<bool>> HasVoted(Guid userId)
    {
        var existingVote = await _context.Votes
            .AnyAsync(v => v.UserId == userId && v.VoteTime.Month == DateTime.Now.Month && v.VoteTime.Year == DateTime.Now.Year);

        return Ok(existingVote);
    }

    [HttpGet("Counts")]
    public async Task<ActionResult<Dictionary<Guid, int>>> GetVoteCounts()
    {
        var voteCounts = await _context.Votes
            .Where(v => v.VoteTime.Month == DateTime.Now.Month && v.VoteTime.Year == DateTime.Now.Year)
            .GroupBy(v => v.GameId)
            .Select(g => new { GameId = g.Key, Count = g.Count() })
            .ToDictionaryAsync(g => g.GameId, g => g.Count);

        return Ok(voteCounts);
    }
}




using ESOF.WebApp.DBLayer.Entities;
using ESOF.WebApp.DBLayer.Context;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ESOF.WebApp.WebAPI.Services
{
    public class VoteService
    {
        private readonly ApplicationDbContext _context;

        public VoteService(ApplicationDbContext context)
        {
            _context = context;
        }

        public async Task<List<Game>> GetGamesAsync()
        {
            return await _context.Games.ToListAsync();
        }

        private async Task<bool> HasUserVotedAsync(Guid userId, int month, int year)
        {
            return await _context.Votes
                .AnyAsync(v => v.UserId == userId && v.VoteTime.Month == month && v.VoteTime.Year == year);
        }

        public async Task<bool> VoteForGameAsync(Vote vote)
        {
            // Verifica se o usuário já votou neste mês (se necessário)
            var hasVoted = await HasUserVotedAsync(vote.UserId, vote.VoteTime.Month, vote.VoteTime.Year);
            if (hasVoted)
            {
                return false; // Ou lance uma exceção informando que o usuário já votou
            }

            _context.Votes.Add(vote);
            var result = await _context.SaveChangesAsync() > 0;
            return result;
        }
        

        public async Task<Dictionary<Guid, int>> GetVoteCountsAsync()
        {
            return await _context.Votes
                .GroupBy(v => v.GameId)
                .Select(g => new { GameId = g.Key, Count = g.Count() })
                .ToDictionaryAsync(g => g.GameId, g => g.Count);
        }
        
        public async Task<Dictionary<Guid, double>> GetVotePercentagesAsync()
        {
            var totalVotes = await _context.Votes.CountAsync();
            if (totalVotes == 0) return new Dictionary<Guid, double>();

            return await _context.Votes
                .GroupBy(v => v.GameId)
                .Select(g => new { GameId = g.Key, Percentage = (double)g.Count() / totalVotes * 100 })
                .ToDictionaryAsync(g => g.GameId, g => g.Percentage);
        }
        
        public async Task<Game?> GetGameOfTheMonthAsync()
        {
            var gameOfTheMonthId = await _context.Votes
                .Where(v => v.VoteTime.Month == DateTime.Now.Month && v.VoteTime.Year == DateTime.Now.Year)
                .GroupBy(v => v.GameId)
                .OrderByDescending(g => g.Count())
                .Select(g => g.Key)
                .FirstOrDefaultAsync();

            if (gameOfTheMonthId == Guid.Empty)
            {
                return null;
            }

            var game = await _context.Games.FindAsync(gameOfTheMonthId);
            return game;
        }
        
        
    }
}

After that code i need make polls with all games, the game what have bigger number of votes will be Game of The Month, the poll will open in the last 5 days of the month and refresh the game of the month in day 1 of the next month.
Can we help me?

After that code i need make polls with all games, the game what have bigger number of votes will be Game of The Month, the poll will open in the last 5 days of the month and refresh the game of the month in day 1 of the next month.
Can we help me?

New contributor

Faria13 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật