Search code examples
c#asp.net-corerazor.net-7.0

WebPage doesnt want to work with controller .net 7.0


I have the Web Project, firstly i create the backend of the functionality and test it at swagger at swagger it`s going good, all correct working but when i'm trying to add this to my front end, it doesnt work and don't want to login or register, here the code.

IAuthService

    public interface IAuthService
    {
        Task<User> RegisterAsync(UserRequestDto request);
        Task<User> LoginAsync(UserRequestLogDto request);
    }
}

AuthService

using Microsoft.EntityFrameworkCore;
using Ryzhanovskyi.University.Tinder.Core.Interfaces;
using Ryzhanovskyi.University.Tinder.Models.Auth;
using Ryzhanovskyi.University.Tinder.Models.Models;
using Ryzhanovskyi.University.Tinder.Web.Data;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ryzhanovskyi.University.Tinder.Core.Services
{
    public class AuthService : IAuthService
    {
        private readonly DataContext _context;
        private readonly IEmailSender _emailSender;

        public AuthService(DataContext context, IEmailSender emailSender)
        {
            _context = context;
            _emailSender = emailSender;
        }

        public async Task<User> RegisterAsync(UserRequestDto request)
        {
            if (await _context.Users.AnyAsync(u => u.Email == request.Email))
            {
                return null; 
            }

            string passwordHash = BCrypt.Net.BCrypt.HashPassword(request.Password);

            var user = new User
            {
                UserName = request.Username,
                Email = request.Email,
                PasswordHash = passwordHash
            };

            var welcomeEmail = new EmailModel
            {
                Email = request.Email,
                Subject = "Mail for successfully registration at GnomeLove",
                Message = $"Welcome {user.UserName} to Dating Web APP GnomeLove, good luck in searching your love ^_^"
            };
            await _emailSender.SendEmailAsync(welcomeEmail.Email, welcomeEmail.Subject, welcomeEmail.Message);

            _context.Users.Add(user);
            await _context.SaveChangesAsync();

            return user; 
        }

        public async Task<User> LoginAsync(UserRequestLogDto request)
        {
            var user = await _context.Users.FirstOrDefaultAsync(u => u.Email == request.Email);

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

            if (!BCrypt.Net.BCrypt.Verify(request.Password, user.PasswordHash))
            {
                return null;
            }

            return user;
        }
    }
}

Authcontroller

using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Ryzhanovskyi.University.Tinder.Core.Interfaces;
using Ryzhanovskyi.University.Tinder.Models.Auth;
using Ryzhanovskyi.University.Tinder.Models.Models;
using Ryzhanovskyi.University.Tinder.Core.Services;

namespace Ryzhanovskyi.University.Tinder.Web.Controllers
{
    [Route("[controller]")]
    [ApiController]
    public class AuthController : ControllerBase
    {
        private readonly IAuthService _authService;

        public AuthController(IAuthService authService)
        {
            _authService = authService;
        }

        [HttpPost("register")]
        public async Task<ActionResult<User>> Register(UserRequestDto request)
        {
            var user = await _authService.RegisterAsync(request);

            if (user == null)
            {
                return BadRequest("Email is already registered.");
            }

            return Ok(user);
        }

        [HttpPost("login")]
        public async Task<ActionResult<User>> Login(UserRequestLogDto request)
        {
            var user = await _authService.LoginAsync(request);

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

            if (user == null)
            {
                return BadRequest("Invalid email or password.");
            }

            return Ok(user);
        }
    }
}

Login.cshtml

@page
@using Ryzhanovskyi.University.Tinder.Models.Auth
@model Ryzhanovskyi.University.Tinder.Web.Pages.Auth.LoginModel

@{
    ViewData["Title"] = "Login";
}

<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-6 card p-4">
            <h2 class="text-center text-info mb-4">Login</h2>

            <form asp-action="Login" method="post">
                <div asp-validation-summary="ModelOnly" class="mb-3"></div>

                <div class="mb-3">
                    <label asp-for="UserRequestLog.Email"></label>
                    <input asp-for="UserRequestLog.Email" class="form-control" />
                    <span asp-validation-for="UserRequestLog.Email" class="text-danger"></span>
                </div>

                <div class="mb-3">
                    <label asp-for="UserRequestLog.Password"></label>
                    <input type="password" asp-for="UserRequestLog.Password" class="form-control" />
                    <span asp-validation-for="UserRequestLog.Password" class="text-danger"></span>
                </div>

                <div class="d-flex justify-content-between align-items-center">
                    <a href="Register" class="text-decoration-none">Don't have an account?</a>
                    <input type="submit" value="Login" class="btn btn-primary" />
                </div>
            </form>
        </div>
    </div>
</div>

@section Scripts{
    @{
        await Html.RenderPartialAsync("_ValidationScriptsPartial");
    }
}

Login.cshtml.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Ryzhanovskyi.University.Tinder.Core.Interfaces;
using Ryzhanovskyi.University.Tinder.Models.Auth;

namespace Ryzhanovskyi.University.Tinder.Web.Pages.Auth
{
    public class LoginModel : PageModel
    {
        private readonly IAuthService _authService;

        public LoginModel(IAuthService authService)
        {
            _authService = authService;
        }

        [BindProperty]
        public UserRequestLogDto UserRequestLog { get; set; }

        public async Task<IActionResult> LoginAsync()
        {
            if (ModelState.IsValid)
            {
                var result = await _authService.LoginAsync(UserRequestLog);

                if (result != null)
                {
                    return RedirectToPage("/main");
                }
                else
                {
                    ModelState.AddModelError(string.Empty, "Wrong Password or Account with this email doesn't exist");
                    return Page();
                }
            }

            return Page();
        }
    }
}

I'm trying a lot, but i work with.net firstly because my teacher from Eleks want that we create a web project at .net and clearly nothing teach us how to do.


Solution

  • First of all, you mentioned "all correct working at Swagger" when testing the Api, so that we could say the controller and the Service should work well. Then you shared Login.cshtml and Login.cshtml.cs, and we injected private readonly IAuthService _authService; into Login.cshtml.cs so that we can say we are not using the API right now, we only use the IAuthService.

    So I created a razor page web app and have a test, I copy and paste the html content in my index.cshtml, this time when I click the Login button, we will send a post request https://localhost:7252/?action=Login, this won't hit the public async Task<IActionResult> LoginAsync() method, after I changing the method name to OnPostAsync instead, the function can be triggered. Then the AuthService could start to work.

    enter image description here

    Let' go back to the error message, 415 error means unsupported media, here's a high voted sample for this error. But I didn't see related settings in codes you shared. I'm afraid we are lacking of information to reproduce the issue. My testing code is like below. By the way, since you are trying to create a Login module, you can also use the default asp.net core identity which containing out of box pages and database table. You could create a new .net 7 web app via VS 2022 template and choose Individual Account as Authentication type after selecting the .net version.

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.RazorPages;
    using WebApp.Models;
    using WebApp.Services;
    
    namespace WebApp.Pages
    {
        public class IndexModel : PageModel
        {
            private readonly ILogger<IndexModel> _logger;
            private readonly IAuthService _authService;
    
    
            public IndexModel(ILogger<IndexModel> logger, IAuthService authService)
            {
                _logger = logger;
                _authService = authService;
            }
    
            [BindProperty]
            public UserRequestLogDto UserRequestLog { get; set; }
    
            public void OnGet()
            {
    
            }
    
            public async Task<IActionResult> OnPostAsync()
            {
                if (ModelState.IsValid)
                {
                    var result = _authService.LoginAsync(UserRequestLog);
    
                    if (result != null)
                    {
                        return RedirectToPage("/privacy");
                    }
                    else
                    {
                        ModelState.AddModelError(string.Empty, "Wrong Password or Account with this email doesn't exist");
                        return Page();
                    }
                }
    
                return Page();
            }
    
        }
    }
    
    
    @page
    @model IndexModel
    @{
        ViewData["Title"] = "Home page";
    }
    
    <div class="text-center">
        <h1 class="display-4">Welcome</h1>
        <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
    </div>
    
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-6 card p-4">
                <h2 class="text-center text-info mb-4">Login</h2>
    
                <form asp-action="Login" method="post">
                    <div asp-validation-summary="ModelOnly" class="mb-3"></div>
    
                    <div class="mb-3">
                        <label asp-for="UserRequestLog.Email"></label>
                        <input asp-for="UserRequestLog.Email" class="form-control" />
                        <span asp-validation-for="UserRequestLog.Email" class="text-danger"></span>
                    </div>
    
                    <div class="mb-3">
                        <label asp-for="UserRequestLog.Password"></label>
                        <input type="password" asp-for="UserRequestLog.Password" class="form-control" />
                        <span asp-validation-for="UserRequestLog.Password" class="text-danger"></span>
                    </div>
    
                    <div class="d-flex justify-content-between align-items-center">
                        <a href="Register" class="text-decoration-none">Don't have an account?</a>
                        <input type="submit" value="Login" class="btn btn-primary" />
                    </div>
                </form>
            </div>
        </div>
    </div>
    
    @section Scripts {
        @{
            await Html.RenderPartialAsync("_ValidationScriptsPartial");
        }
    }