A lightweight wrapper around libsass.
LibSass is a C/C++ port of the Sass CSS precompiler.
LibSass is a C/C++ port of the Sass CSS precompiler.
نحوه استفاده را میتوانید در این صفحه مشاهده نمایید.
TempData["PaymentMethodsWithshippingMethods"]= await _paymentMethodService.FindAllWithShippingMethodsAsync();
var paymentMethodsWithshippingMethods = TempData .Where(x => x.Key.Contains("PaymentMethodsWithshippingMethods")) .Select(x => new { value = (PaymentMethodViewModel)x.Value }) .Select(x => new PaymentMethodViewModel { PaymentMethodId = x.value.PaymentMethodId, Type = x.value.Type, ShippingMethods = x.value.ShippingMethods.Select(y => new ShippingMethodViewModel { ShippingMethodId = y.ShippingMethodId, DiscountPrice = y.DiscountPrice, ProductPrice = y.ProductPrice, Tax = y.Tax, Type = y.Type, Cost = y.Cost, }).ToList() }).ToList();
Unable to cast object of type 'System.Collections.Generic.List`1[MeMarketShop.ViewModel.PaymentMethod.PaymentMethodViewModel]' to type 'MeMarketShop.ViewModel.PaymentMethod.PaymentMethodViewModel'.
public class IrisPasswordHasher : IPasswordHasher { public string HashPassword(string password) { return Utilities.Security.Encryption.EncryptingPassword(password); } public PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword) { return Utilities.Security.Encryption.VerifyPassword(providedPassword, hashedPassword) ? PasswordVerificationResult.Success : PasswordVerificationResult.Failed; } }
public ApplicationUserManager(IUserStore<ApplicationUser, int> store, IUnitOfWork uow, IIdentity identity, IApplicationRoleManager roleManager, IDataProtectionProvider dataProtectionProvider, IIdentityMessageService smsService, IIdentityMessageService emailService, IPasswordHasher passwordHasher) : base(store) { _store = store; _uow = uow; _identity = identity; _users = _uow.Set<ApplicationUser>(); _roleManager = roleManager; _dataProtectionProvider = dataProtectionProvider; this.SmsService = smsService; this.EmailService = emailService; PasswordHasher = passwordHasher; createApplicationUserManager(); }
x.For<IPasswordHasher>().Use<IrisPasswordHasher>();
[HttpPost] [ValidateAntiForgeryToken] [CaptchaVerify("تصویر امنیتی وارد شده معتبر نیست")] public virtual async Task<ActionResult> Register(RegisterModel model) { if (ModelState.IsValid) { var user = new ApplicationUser { CreatedDate = DateAndTime.GetDateTime(), Email = model.Email, IP = Request.ServerVariables["REMOTE_ADDR"], IsBaned = false, UserName = model.UserName, UserMetaData = new UserMetaData(), LastLoginDate = DateAndTime.GetDateTime() }; var result = await _userManager.CreateAsync(user, model.Password); if (result.Succeeded) { var addToRoleResult = await _userManager.AddToRoleAsync(user.Id, "user"); if (addToRoleResult.Succeeded) { var code = await _userManager.GenerateEmailConfirmationTokenAsync(user.Id); var callbackUrl = Url.Action("ConfirmEmail", "User", new { userId = user.Id, code }, protocol: Request.Url.Scheme); _emailService.SendAccountConfirmationEmail(user.Email, callbackUrl); return Json(new { result = "success" }); } addErrors(addToRoleResult); } addErrors(result); } return PartialView(MVC.User.Views._Register, model); }
public SendingMailResult SendAccountConfirmationEmail(string email, string link) { var model = new ConfirmEmailModel() { ActivationLink = link }; var htmlText = _viewConvertor.RenderRazorViewToString(MVC.EmailTemplates.Views._ConfirmEmail, model); var result = Send(new MailDocument { Body = htmlText, Subject = "تایید حساب کاربری", ToEmail = email }); return result; }
@model Iris.Model.EmailModel.ConfirmEmailModel <div style="direction: rtl; -ms-word-wrap: break-word; word-wrap: break-word;"> <p>با سلام</p> <p>برای فعال سازی حساب کاربری خود لطفا بر روی لینک زیر کلیک کنید:</p> <p>@Model.ActivationLink</p> <div style=" color: #808080;"> <p>با تشکر</p> <p>@Model.SiteTitle</p> <p>@Model.SiteDescription</p> <p><span style="direction: ltr !important; unicode-bidi: embed;">@Html.ConvertToPersianDateTime(DateTime.Now, "s,H")</span></p> </div> </div>
RegisterUser.Form.onSuccess = function (data) { if (data.result == "success") { var message = '<div id="alert"><button type="button" data-dismiss="alert">×</button>ایمیلی حاوی لینک فعال سازی، به ایمیل شما ارسال شد؛ لطفا به ایمیل خود مراجعه کرده و بر روی لینک فعال سازی کلیک کنید.</div>'; $('#registerResult').html(message); } else { $('#logOnModal').html(data); } };
[AllowAnonymous] public virtual async Task<ActionResult> ConfirmEmail(int? userId, string code) { if (userId == null || code == null) { return View("Error"); } var result = await _userManager.ConfirmEmailAsync(userId.Value, code); return View(result.Succeeded ? "ConfirmEmail" : "Error"); }
@{ ViewBag.Title = "حساب کاربری شما تایید شد"; } <h2>@ViewBag.Title.</h2> <div> <p> با تشکر از شما، حساب کاربری شما تایید شد. </p> <p> @Ajax.ActionLink("ورود / ثبت نام", MVC.User.ActionNames.LogOn, MVC.User.Name, new { area = "", returnUrl = Html.ReturnUrl(Context, Url) }, new AjaxOptions { HttpMethod = "GET", InsertionMode = InsertionMode.Replace, UpdateTargetId = "logOnModal", LoadingElementDuration = 300, LoadingElementId = "loadingMessage", OnSuccess = "LogOnForm.onSuccess" }, new { role = "button", data_toggle = "modal", data_i_logon_link = "true", rel = "nofollow" }) </p> </div>
[HttpPost] [ValidateAntiForgeryToken] public async virtual Task<ActionResult> LogOn(LogOnModel model, string returnUrl) { if (!ModelState.IsValid) { if (Request.IsAjaxRequest()) return PartialView(MVC.User.Views._LogOn, model); return View(model); } const string emailRegPattern = @"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$"; string ip = Request.ServerVariables["REMOTE_ADDR"]; SignInStatus result = SignInStatus.Failure; if (Regex.IsMatch(model.Identity, emailRegPattern)) { var user = await _userManager.FindByEmailAsync(model.Identity); if (user != null) { result = await _signInManager.PasswordSignInAsync (user.UserName, model.Password, model.RememberMe, shouldLockout: true); } } else { result = await _signInManager.PasswordSignInAsync(model.Identity, model.Password, model.RememberMe, shouldLockout: true); } switch (result) { case SignInStatus.Success: if (Request.IsAjaxRequest()) return JavaScript(IsValidReturnUrl(returnUrl) ? string.Format("window.location ='{0}';", returnUrl) : "window.location.reload();"); return redirectToLocal(returnUrl); case SignInStatus.LockedOut: ModelState.AddModelError("", string.Format("حساب شما قفل شد، لطفا بعد از {0} دقیقه دوباره امتحان کنید.", _userManager.DefaultAccountLockoutTimeSpan.Minutes)); break; case SignInStatus.Failure: ModelState.AddModelError("", "نام کاربری یا کلمه عبور اشتباه است."); break; default: ModelState.AddModelError("", "در ورود شما خطایی رخ داده است."); break; } if (Request.IsAjaxRequest()) return PartialView(MVC.User.Views._LogOn, model); return View(model); }
[HttpPost] [ValidateAntiForgeryToken] [Authorize] public virtual ActionResult LogOut() { _authenticationManager.SignOut(); if (Request.IsAjaxRequest()) return Json(new { result = "true" }); return RedirectToAction(MVC.User.ActionNames.LogOn, MVC.User.Name); }
using System.Threading.Tasks; using System.Web.Mvc; using CaptchaMvc.Attributes; using Iris.Model; using Iris.Servicelayer.Interfaces; using Iris.Web.Email; using Microsoft.AspNet.Identity; namespace Iris.Web.Controllers { public partial class ForgottenPasswordController : Controller { private readonly IEmailService _emailService; private readonly IApplicationUserManager _userManager; public ForgottenPasswordController(IEmailService emailService, IApplicationUserManager applicationUserManager) { _emailService = emailService; _userManager = applicationUserManager; } [HttpGet] public virtual ActionResult Index() { return PartialView(MVC.ForgottenPassword.Views._Index); } [HttpPost] [ValidateAntiForgeryToken] [CaptchaVerify("تصویر امنیتی وارد شده معتبر نیست")] public async virtual Task<ActionResult> Index(ForgottenPasswordModel model) { if (!ModelState.IsValid) { return PartialView(MVC.ForgottenPassword.Views._Index, model); } var user = await _userManager.FindByEmailAsync(model.Email); if (user == null || !(await _userManager.IsEmailConfirmedAsync(user.Id))) { // Don't reveal that the user does not exist or is not confirmed return Json(new { result = "false", message = "این ایمیل در سیستم ثبت نشده است" }); } var code = await _userManager.GeneratePasswordResetTokenAsync(user.Id); _emailService.SendResetPasswordConfirmationEmail(user.UserName, user.Email, code); return Json(new { result = "true", message = "ایمیلی برای تایید بازنشانی کلمه عبور برای شما ارسال شد.اعتبارایمیل ارسالی 3 ساعت است." }); } [AllowAnonymous] public virtual ActionResult ResetPassword(string code) { return code == null ? View("Error") : View(); } [AllowAnonymous] public virtual ActionResult ResetPasswordConfirmation() { return View(); } // // POST: /Account/ResetPassword [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public virtual async Task<ActionResult> ResetPassword(ResetPasswordViewModel model) { if (!ModelState.IsValid) { return View(model); } var user = await _userManager.FindByEmailAsync(model.Email); if (user == null) { // Don't reveal that the user does not exist return RedirectToAction("Error"); } var result = await _userManager.ResetPasswordAsync(user.Id, model.Code, model.Password); if (result.Succeeded) { return RedirectToAction("ResetPasswordConfirmation", "ForgottenPassword"); } addErrors(result); return View(); } private void addErrors(IdentityResult result) { foreach (var error in result.Errors) { ModelState.AddModelError("", error); } } } }
@{ ViewBag.Title = "کلمه عبور شما تغییر کرد"; } <hgroup> <h1>@ViewBag.Title.</h1> </hgroup> <div> <p> کلمه عبور شما با موفقیت تغییر کرد </p> <p> @Ajax.ActionLink("ورود / ثبت نام", MVC.User.ActionNames.LogOn, MVC.User.Name, new { area = "", returnUrl = Html.ReturnUrl(Context, Url) }, new AjaxOptions { HttpMethod = "GET", InsertionMode = InsertionMode.Replace, UpdateTargetId = "logOnModal", LoadingElementDuration = 300, LoadingElementId = "loadingMessage", OnSuccess = "LogOnForm.onSuccess" }, new { role = "button", data_toggle = "modal", data_i_logon_link = "true", rel = "nofollow" }) </p> </div>
@model Iris.Model.ResetPasswordViewModel @{ ViewBag.Title = "ریست کردن کلمه عبور"; } <h2>@ViewBag.Title.</h2> @using (Html.BeginForm("ResetPassword", "ForgottenPassword", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) { @Html.AntiForgeryToken() <h4>ریست کردن کلمه عبور</h4> <hr /> @Html.ValidationSummary("", new { @class = "text-danger" }) @Html.HiddenFor(model => model.Code) <div> @Html.LabelFor(m => m.Email, "ایمیل", new { @class = "control-label" }) <div> @Html.TextBoxFor(m => m.Email) </div> </div> <div> @Html.LabelFor(m => m.Password, "کلمه عبور", new { @class = "control-label" }) <div> @Html.PasswordFor(m => m.Password) </div> </div> <div> @Html.LabelFor(m => m.ConfirmPassword, "تکرار کلمه عبور", new { @class = "control-label" }) <div> @Html.PasswordFor(m => m.ConfirmPassword) </div> </div> <div> <div> <input type="submit" value="تغییر کلمه عبور" /> </div> </div> }
using System.ComponentModel.DataAnnotations; namespace Iris.Model { public class ResetPasswordViewModel { [Required] [EmailAddress] [Display(Name = "ایمیل")] public string Email { get; set; } [Required] [StringLength(100, ErrorMessage = "کلمه عبور باید حداقل 6 حرف باشد", MinimumLength = 6)] [DataType(DataType.Password)] [Display(Name = "کلمه عبور")] public string Password { get; set; } [DataType(DataType.Password)] [Display(Name = "تکرار کلمه عبور")] [Compare("Password", ErrorMessage = "کلمه عبور و تکرارش یکسان نیستند")] public string ConfirmPassword { get; set; } public string Code { get; set; } } }
var principalService = ObjectFactory.GetInstance<IPrincipalService>(); var formsAuthenticationService = ObjectFactory.GetInstance<IFormsAuthenticationService>(); context.User = principalService.GetCurrent()
public class CustomUserValidator<TUser, TKey> : IIdentityValidator<ApplicationUser> where TUser : class, IUser<int> where TKey : IEquatable<int> { public bool AllowOnlyAlphanumericUserNames { get; set; } public bool RequireUniqueEmail { get; set; } private ApplicationUserManager Manager { get; set; } public CustomUserValidator(ApplicationUserManager manager) { if (manager == null) throw new ArgumentNullException("manager"); AllowOnlyAlphanumericUserNames = true; Manager = manager; } public virtual async Task<IdentityResult> ValidateAsync(ApplicationUser item) { if (item == null) throw new ArgumentNullException("item"); var errors = new List<string>(); await ValidateUserName(item, errors); if (RequireUniqueEmail) await ValidateEmailAsync(item, errors); return errors.Count <= 0 ? IdentityResult.Success : IdentityResult.Failed(errors.ToArray()); } private async Task ValidateUserName(ApplicationUser user, ICollection<string> errors) { if (string.IsNullOrWhiteSpace(user.UserName)) errors.Add("نام کاربری نباید خالی باشد"); else if (AllowOnlyAlphanumericUserNames && !Regex.IsMatch(user.UserName, "^[A-Za-z0-9@_\\.]+$")) { errors.Add("برای نام کاربری فقط از کاراکترهای مجاز استفاده کنید "); } else { var owner = await Manager.FindByNameAsync(user.UserName); if (owner != null && !EqualityComparer<int>.Default.Equals(owner.Id, user.Id)) errors.Add("این نام کاربری قبلا ثبت شده است"); } } private async Task ValidateEmailAsync(ApplicationUser user, ICollection<string> errors) { var email = await Manager.GetEmailStore().GetEmailAsync(user).WithCurrentCulture(); if (string.IsNullOrWhiteSpace(email)) { errors.Add("وارد کردن ایمیل ضروریست"); } else { try { var m = new MailAddress(email); } catch (FormatException) { errors.Add("ایمیل را به شکل صحیح وارد کنید"); return; } var owner = await Manager.FindByEmailAsync(email); if (owner != null && !EqualityComparer<int>.Default.Equals(owner.Id, user.Id)) errors.Add("این ایمیل قبلا ثبت شده است"); } } }
public class CustomPasswordValidator : IIdentityValidator<string> { #region Properties public int RequiredLength { get; set; } public bool RequireNonLetterOrDigit { get; set; } public bool RequireLowercase { get; set; } public bool RequireUppercase { get; set; } public bool RequireDigit { get; set; } #endregion #region IIdentityValidator public virtual Task<IdentityResult> ValidateAsync(string item) { if (item == null) throw new ArgumentNullException("item"); var list = new List<string>(); if (string.IsNullOrWhiteSpace(item) || item.Length < RequiredLength) list.Add(string.Format("کلمه عبور نباید کمتر از 6 کاراکتر باشد")); if (RequireNonLetterOrDigit && item.All(IsLetterOrDigit)) list.Add("برای امنیت بیشتر از حداقل از یک کارکتر غیر عددی و غیر حرف برای کلمه عبور استفاده کنید"); if (RequireDigit && item.All(c => !IsDigit(c))) list.Add("برای امنیت بیشتر از اعداد هم در کلمه عبور استفاده کنید"); if (RequireLowercase && item.All(c => !IsLower(c))) list.Add("از حروف کوچک نیز برای کلمه عبور استفاده کنید"); if (RequireUppercase && item.All(c => !IsUpper(c))) list.Add("از حروف بزرک نیز برای کلمه عبور استفاده کنید"); return Task.FromResult(list.Count == 0 ? IdentityResult.Success : IdentityResult.Failed(string.Join(" ", list))); } #endregion #region PrivateMethods public virtual bool IsDigit(char c) { if (c >= 48) return c <= 57; return false; } public virtual bool IsLower(char c) { if (c >= 97) return c <= 122; return false; } public virtual bool IsUpper(char c) { if (c >= 65) return c <= 90; return false; } public virtual bool IsLetterOrDigit(char c) { if (!IsUpper(c) && !IsLower(c)) return IsDigit(c); return true; } #endregion }
UserValidator = new CustomUserValidator< ApplicationUser, int>(this) { AllowOnlyAlphanumericUserNames = false, RequireUniqueEmail = true }; PasswordValidator = new CustomPasswordValidator { RequiredLength = 6, RequireNonLetterOrDigit = false, RequireDigit = false, RequireLowercase = false, RequireUppercase = false };
public virtual async Task<ActionResult> UpdateAllUsersSecurityStamp() { foreach (var user in await _userManager.GetAllUsersAsync()) { await _userManager.UpdateSecurityStampAsync(user.Id); } return Content("ok"); }
public virtual async Task<ActionResult> CopyRoleToNewTable() { var dbContext = new IrisDbContext(); foreach (var role in await dbContext.Roles.ToListAsync()) { await _roleManager.CreateAsync(new CustomRole(role.Name) { Description = role.Description }); } var users = await dbContext.Users.Include(u => u.Role).ToListAsync(); foreach (var user in users) { await _userManager.AddToRoleAsync(user.Id, user.Role.Name); } return Content("ok"); }
<div id="blazor-error-ui"> An unhandled error has occurred. <a href="" class="reload">Reload</a> <a class="dismiss">🗙</a> </div>
using System; using System.Net.Http; using Microsoft.AspNetCore.Components; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace BlazorWasmTelegramLogger.Client.Logging { public class ClientLoggerProvider : ILoggerProvider { private readonly HttpClient _httpClient; private readonly WebApiLoggerOptions _options; private readonly NavigationManager _navigationManager; public ClientLoggerProvider( IServiceProvider serviceProvider, IOptions<WebApiLoggerOptions> options, NavigationManager navigationManager) { if (serviceProvider is null) { throw new ArgumentNullException(nameof(serviceProvider)); } if (options is null) { throw new ArgumentNullException(nameof(options)); } _httpClient = serviceProvider.CreateScope().ServiceProvider.GetRequiredService<HttpClient>(); _options = options.Value; _navigationManager = navigationManager ?? throw new ArgumentNullException(nameof(navigationManager)); } public ILogger CreateLogger(string categoryName) { return new WebApiLogger(_httpClient, _options, _navigationManager); } public void Dispose() { } } }
using System; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace BlazorWasmTelegramLogger.Client.Logging { public static class ClientLoggerProviderExtensions { public static ILoggingBuilder AddWebApiLogger(this ILoggingBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } builder.Services.AddSingleton<ILoggerProvider, ClientLoggerProvider>(); return builder; } } }
public ClientLoggerProvider( IServiceProvider serviceProvider, IOptions<WebApiLoggerOptions> options, NavigationManager navigationManager)
public ILogger CreateLogger(string categoryName) { return new WebApiLogger(_httpClient, _options, _navigationManager); }
using System; using System.Net.Http; using System.Net.Http.Json; using BlazorWasmTelegramLogger.Shared; using Microsoft.AspNetCore.Components; using Microsoft.Extensions.Logging; namespace BlazorWasmTelegramLogger.Client.Logging { public class WebApiLogger : ILogger { private readonly WebApiLoggerOptions _options; private readonly HttpClient _httpClient; private readonly NavigationManager _navigationManager; public WebApiLogger(HttpClient httpClient, WebApiLoggerOptions options, NavigationManager navigationManager) { _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); _options = options ?? throw new ArgumentNullException(nameof(options)); _navigationManager = navigationManager ?? throw new ArgumentNullException(nameof(navigationManager)); } public IDisposable BeginScope<TState>(TState state) => default; public bool IsEnabled(LogLevel logLevel) => logLevel >= _options.LogLevel; public void Log<TState>( LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) { if (!IsEnabled(logLevel)) { return; } if (formatter is null) { throw new ArgumentNullException(nameof(formatter)); } try { ClientLog log = new() { LogLevel = logLevel, EventId = eventId, Message = formatter(state, exception), Exception = exception?.Message, StackTrace = exception?.StackTrace, Url = _navigationManager.Uri }; _httpClient.PostAsJsonAsync(_options.LoggerEndpointUrl, log); } catch { // don't throw exceptions from the logger } } } }
using Microsoft.Extensions.Logging; namespace BlazorWasmTelegramLogger.Client.Logging { public class WebApiLoggerOptions { public string LoggerEndpointUrl { set; get; } public LogLevel LogLevel { get; set; } = LogLevel.Information; } }
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "WebApiLogger": { "LogLevel": "Warning", "LoggerEndpointUrl": "/api/logs" } }
namespace BlazorWasmTelegramLogger.Client { public class Program { public static async Task Main(string[] args) { var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add<App>("#app"); builder.Services.Configure<WebApiLoggerOptions>(options => builder.Configuration.GetSection("WebApiLogger").Bind(options)); // … } } }
using Microsoft.Extensions.Logging; namespace BlazorWasmTelegramLogger.Shared { public class ClientLog { public LogLevel LogLevel { get; set; } public EventId EventId { get; set; } public string Message { get; set; } public string Exception { get; set; } public string StackTrace { get; set; } public string Url { get; set; } } }
namespace BlazorWasmTelegramLogger.Client { public class Program { public static async Task Main(string[] args) { var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add<App>("#app"); builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); builder.Services.Configure<WebApiLoggerOptions>(options => builder.Configuration.GetSection("WebApiLogger").Bind(options)); builder.Services.AddLogging(configure => { configure.AddWebApiLogger(); }); await builder.Build().RunAsync(); } } }
public bool IsEnabled(LogLevel logLevel) => logLevel >= _options.LogLevel;
using System; using System.Text; using System.Threading.Tasks; using BlazorWasmTelegramLogger.Shared; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Telegram.Bot; using Telegram.Bot.Types.Enums; namespace BlazorWasmTelegramLogger.Server.Services { public class TelegramLoggingBotOptions { public string AccessToken { get; set; } public string ChatId { get; set; } } public interface ITelegramBotService { Task SendLogAsync(ClientLog log); } public class TelegramBotService : ITelegramBotService { private readonly string _chatId; private readonly TelegramBotClient _client; public TelegramBotService(IOptions<TelegramLoggingBotOptions> options) { _chatId = options.Value.ChatId; _client = new TelegramBotClient(options.Value.AccessToken); } public async Task SendLogAsync(ClientLog log) { var text = formatMessage(log); if (string.IsNullOrWhiteSpace(text)) { return; } await _client.SendTextMessageAsync(_chatId, text, ParseMode.Markdown); } private static string formatMessage(ClientLog log) { if (string.IsNullOrWhiteSpace(log.Message)) { return string.Empty; } var sb = new StringBuilder(); sb.Append(toEmoji(log.LogLevel)) .Append(" *") .AppendFormat("{0:hh:mm:ss}", DateTime.Now) .Append("* ") .AppendLine(log.Message); if (!string.IsNullOrWhiteSpace(log.Exception)) { sb.AppendLine() .Append('`') .AppendLine(log.Exception) .AppendLine(log.StackTrace) .AppendLine("`") .AppendLine(); } sb.Append("*Url:* ").AppendLine(log.Url); return sb.ToString(); } private static string toEmoji(LogLevel level) => level switch { LogLevel.Trace => "⬜️", LogLevel.Debug => "🟦", LogLevel.Information => "⬛️️️", LogLevel.Warning => "🟧", LogLevel.Error => "🟥", LogLevel.Critical => "❌", LogLevel.None => "🔳", _ => throw new ArgumentOutOfRangeException(nameof(level), level, null) }; } }
<Project Sdk="Microsoft.NET.Sdk.Web"> <ItemGroup> <PackageReference Include="Telegram.Bot" Version="15.7.1" /> </ItemGroup> </Project>
public class TelegramLoggingBotOptions { public string AccessToken { get; set; } public string ChatId { get; set; } }
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", "TelegramLoggingBot": { "AccessToken": "1826…", "ChatId": "-1001…" } }
namespace BlazorWasmTelegramLogger.Server { public class Startup { // ... public void ConfigureServices(IServiceCollection services) { services.Configure<TelegramLoggingBotOptions>(options => Configuration.GetSection("TelegramLoggingBot").Bind(options)); services.AddSingleton<ITelegramBotService, TelegramBotService>(); // ... } // ... } }
public class TelegramBotService : ITelegramBotService { private readonly string _chatId; private readonly TelegramBotClient _client; public TelegramBotService(IOptions<TelegramLoggingBotOptions> options) { _chatId = options.Value.ChatId; _client = new TelegramBotClient(options.Value.AccessToken); }
using System; using System.Threading.Tasks; using BlazorWasmTelegramLogger.Server.Services; using BlazorWasmTelegramLogger.Shared; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; namespace BlazorWasmTelegramLogger.Server.Controllers { [ApiController] [Route("api/[controller]")] public class LogsController : ControllerBase { private readonly ILogger<LogsController> _logger; private readonly ITelegramBotService _telegramBotService; public LogsController(ILogger<LogsController> logger, ITelegramBotService telegramBotService) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _telegramBotService = telegramBotService; } [HttpPost] public async Task<IActionResult> PostLog(ClientLog log) { // TODO: Save the client's `log` in the database _logger.Log(log.LogLevel, log.EventId, log.Url + Environment.NewLine + log.Message); await _telegramBotService.SendLogAsync(log); return Ok(); } } }
@page "/counter" <h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; throw new InvalidOperationException("This is an exception message from the client!"); } }
>npm install ng2-file-upload --save
>ng g c UploadFile/ng2-file-upload-test
import { FileUploadModule } from "ng2-file-upload"; @NgModule({ imports: [ FileUploadModule ]
import { FileUploader, FileUploaderOptions } from "ng2-file-upload"; import { Ticket } from "./../ticket"; export class Ng2FileUploadTestComponent implements OnInit { fileUploader: FileUploader; model = new Ticket();
this.fileUploader = new FileUploader( <FileUploaderOptions>{ url: "api/SimpleUpload/SaveTicket", headers: [ { name: "X-XSRF-TOKEN", value: this.getCookie("XSRF-TOKEN") }, { name: "Accept", value: "application/json" } ], isHTML5: true, // allowedMimeType: ["image/jpeg", "image/png", "application/pdf", "application/msword", "application/zip"] allowedFileType: [ "application", "image", "video", "audio", "pdf", "compress", "doc", "xls", "ppt" ], removeAfterUpload: true, autoUpload: false, maxFileSize: 10 * 1024 * 1024 } );
getCookie(name: string): string { const value = "; " + document.cookie; const parts = value.split("; " + name + "="); if (parts.length === 2) { return decodeURIComponent(parts.pop().split(";").shift()); } }
this.fileUploader.onBuildItemForm = (fileItem, form) => { for (const key in this.model) { if (this.model.hasOwnProperty(key)) { form.append(key, this.model[key]); } } };
this.fileUploader.onCompleteAll = () => { // clear the form // this.model = new Ticket(); };
this.fileUploader.onWhenAddingFileFailed = (item, filter, options) => { // msg: `You can't select ${item.name} file because of the ${filter.name} filter.` };
this.fileUploader.onErrorItem = (fileItem, response, status, headers) => { // };
this.fileUploader.onSuccessItem = (item, response, status, headers) => { if (response) { const ticket = JSON.parse(response); console.log(`ticket:`, ticket); } };
submitForm(form: NgForm) { this.fileUploader.uploadAll(); // NOTE: Upload multiple files in one request -> https://github.com/valor-software/ng2-file-upload/issues/671 }
<div class="container"> <h3>Support Form(ng2-file-upload)</h3> <form #form="ngForm" (submit)="submitForm(form)" novalidate> <div class="form-group" [class.has-error]="description.invalid && description.touched"> <label class="control-label">Description</label> <input #description="ngModel" required type="text" class="form-control" name="description" [(ngModel)]="model.description"> <div *ngIf="description.invalid && description.touched"> <div class="alert alert-danger" *ngIf="description.errors.required"> description is required. </div> </div> </div>
<div class="form-group"> <label class="control-label">Screenshot(s)</label> <input required type="file" multiple ng2FileSelect [uploader]="fileUploader" class="form-control" name="screenshot"> </div>
<div style="margin-bottom: 10px" *ngIf="fileUploader.queue.length"> <h3>Upload queue</h3> <p>Queue length: {{ fileUploader?.queue?.length }}</p> <table class="table"> <thead> <tr> <th width="50%">Name</th> <th>Size</th> <th>Progress</th> <th>Status</th> <th>Actions</th> </tr> </thead> <tbody> <tr *ngFor="let item of fileUploader.queue"> <td><strong>{{ item?.file?.name }}</strong></td> <td nowrap>{{ item?.file?.size/1024/1024 | number:'.2' }} MB</td> <td> <div class="progress" style="margin-bottom: 0;"> <div class="progress-bar" role="progressbar" [ngStyle]="{ 'width': item.progress + '%' }"></div> </div> </td> <td class="text-center"> <span *ngIf="item.isError"><i class="glyphicon glyphicon-remove"></i></span> </td> <td nowrap> <button type="button" class="btn btn-danger btn-xs" (click)="item.remove()"> <span class="glyphicon glyphicon-trash"></span> Remove </button> </td> </tr> </tbody> </table> <div> <div> Queue progress: <div class="progress"> <div class="progress-bar" role="progressbar" [ngStyle]="{ 'width': fileUploader.progress + '%' }"></div> </div> </div> <button type="button" class="btn btn-danger btn-s" (click)="fileUploader.clearQueue()" [disabled]="!fileUploader.queue.length"> <span class="glyphicon glyphicon-trash"></span> Remove all </button> </div> </div>
<div class="progress" style="margin-bottom: 0;"> <div class="progress-bar" role="progressbar" [ngStyle]="{ 'width': item.progress + '%' }"></div> </div>
<button class="btn btn-primary" [disabled]="form.invalid || !fileUploader.queue.length" type="submit">Submit</button> </form>
The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.0 Must issue a STARTTLS command first
<system.net> <mailSettings> <smtp> <network enableSsl="true"/> </smtp> </mailSettings> </system.net>
<EditForm Model="@selectedCar" OnValidSubmit="@SaveObject"> <DataAnnotationsValidator /> <ValidationSummary /> ....My <InputText>'s for all values I have in my object <button type="submit" value="Save">Save</button> </EditForm> @code { [Parameter] public string Id { get; set; } CarModel selectedCar; protected override async Task OnInitializedAsync() { selectedCar = await _CarService.GetCar(int.Parse(Id)); } protected async Task SaveObject() { selectedCar.Id = await _CarService.SaveCar(selectedCar); } }
<EditForm Model="@selectedCar" Context="formContext"> <DataAnnotationsValidator /> <ValidationSummary /> ....My <InputText>'s for all values I have in my object <button type="submit" @onclick="@(() => SaveCar(formContext))">Save</button> <button type="submit" @onclick="@(() => UpdateStockQuantity(formContext))">Update stock quantity</button> <button type="submit" @onclick="@(() => DeleteCar(formContext))">Delete</button> </EditForm> @code { [Parameter] public string Id { get; set; } CarModel selectedCar; protected override async Task OnInitializedAsync() { selectedCar = await _CarService.GetCar(int.Parse(Id)); } protected async Task SaveCar(EditContext formContext) { bool formIsValid = formContext.Validate(); if (formIsValid == false) return; selectedCar.Id = await _CarService.SaveCar(selectedCar); } protected async Task DeleteObject(EditContext formContext) { selectedCar.Id = await _CarService.DeleteCar(selectedCar); } // ... plus same approach with UpdateStockQuantity. }
>ng g c Dashboard/CallProtectedApi
import { CallProtectedApiComponent } from "./call-protected-api/call-protected-api.component"; const routes: Routes = [ { path: "callProtectedApi", component: CallProtectedApiComponent, data: { permission: { permittedRoles: ["Admin", "User"], deniedRoles: null } as AuthGuardPermission }, canActivate: [AuthGuard] } ];
<li *ngIf="isLoggedIn" routerLinkActive="active"> <a [routerLink]="['/callProtectedApi']">Call Protected Api</a> </li>
import { Component, OnInit } from "@angular/core"; import { AuthService } from "../../core/services/auth.service"; @Component({ selector: "app-call-protected-api", templateUrl: "./call-protected-api.component.html", styleUrls: ["./call-protected-api.component.css"] }) export class CallProtectedApiComponent implements OnInit { isAdmin = false; isUser = false; result: any; constructor(private authService: AuthService) { } ngOnInit() { this.isAdmin = this.authService.isAuthUserInRole("Admin"); this.isUser = this.authService.isAuthUserInRole("User"); } callMyProtectedAdminApiController() { } callMyProtectedApiController() { } }
<button *ngIf="isAdmin" (click)="callMyProtectedAdminApiController()"> Call Protected Admin API [Authorize(Roles = "Admin")] </button> <button *ngIf="isAdmin || isUser" (click)="callMyProtectedApiController()"> Call Protected API ([Authorize]) </button> <div *ngIf="result"> <pre>{{result | json}}</pre> </div>
getBearerAuthHeader(): HttpHeaders { return new HttpHeaders({ "Content-Type": "application/json", "Authorization": `Bearer ${this.getRawAuthToken(AuthTokenType.AccessToken)}` }); }
import { Injectable } from "@angular/core"; import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from "@angular/common/http"; import { Observable } from "rxjs/Observable"; import { AuthService, AuthTokenType } from "./auth.service"; @Injectable() export class AuthInterceptor implements HttpInterceptor { constructor(private authService: AuthService) { } intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const accessToken = this.authService.getRawAuthToken(AuthTokenType.AccessToken); if (accessToken) { request = request.clone({ headers: request.headers.set("Authorization", `Bearer ${accessToken}`) }); } return next.handle(request); } }
import { HTTP_INTERCEPTORS } from "@angular/common/http"; import { AuthInterceptor } from "./services/auth.interceptor"; @NgModule({ providers: [ { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true } ] }) export class CoreModule {}
compiler.js:19514 Uncaught Error: Provider parse errors: Cannot instantiate cyclic dependency! InjectionToken_HTTP_INTERCEPTORS ("[ERROR ->]"): in NgModule AppModule in ./AppModule@-1:-1
import { Injector } from "@angular/core"; constructor(private injector: Injector) { } intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const authService = this.injector.get(AuthService);
@Injectable() export class AuthInterceptor implements HttpInterceptor { constructor(private injector: Injector) { } intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const authService = this.injector.get(AuthService); const accessToken = authService.getRawAuthToken(AuthTokenType.AccessToken); if (accessToken) { request = request.clone({ headers: request.headers.set("Authorization", `Bearer ${accessToken}`) }); } return next.handle(request); } }
constructor( private authService: AuthService, private httpClient: HttpClient, @Inject(APP_CONFIG) private appConfig: IAppConfig, ) { }
callMyProtectedAdminApiController() { this.httpClient .get(`${this.appConfig.apiEndpoint}/MyProtectedAdminApi`) .map(response => response || {}) .catch((error: HttpErrorResponse) => Observable.throw(error)) .subscribe(result => { this.result = result; }); } callMyProtectedApiController() { this.httpClient .get(`${this.appConfig.apiEndpoint}/MyProtectedApi`) .map(response => response || {}) .catch((error: HttpErrorResponse) => Observable.throw(error)) .subscribe(result => { this.result = result; }); }
return next.handle(request) .catch((error: any, caught: Observable<HttpEvent<any>>) => { if (error.status === 401 || error.status === 403) { this.router.navigate(["/accessDenied"]); } return Observable.throw(error); });
@Injectable() export class AuthInterceptor implements HttpInterceptor { constructor( private injector: Injector, private router: Router) { } intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const authService = this.injector.get(AuthService); const accessToken = authService.getRawAuthToken(AuthTokenType.AccessToken); if (accessToken) { request = request.clone({ headers: request.headers.set("Authorization", `Bearer ${accessToken}`) }); return next.handle(request) .catch((error: any, caught: Observable<HttpEvent<any>>) => { if (error.status === 401 || error.status === 403) { this.router.navigate(["/accessDenied"]); } return Observable.throw(error); }); } else { // login page return next.handle(request); } } }
using ASPNETCore2JwtAuthentication.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; namespace ASPNETCore2JwtAuthentication.WebApp.Controllers { [Route("api/[controller]")] [EnableCors("CorsPolicy")] [Authorize(Policy = CustomRoles.Editor)] public class MyProtectedEditorsApiController : Controller { public IActionResult Get() { return Ok(new { Id = 1, Title = "Hello from My Protected Editors Controller! [Authorize(Policy = CustomRoles.Editor)]", Username = this.User.Identity.Name }); } } }
callMyProtectedEditorsApiController() { this.httpClient .get(`${this.appConfig.apiEndpoint}/MyProtectedEditorsApi`) .map(response => response || {}) .catch((error: HttpErrorResponse) => Observable.throw(error)) .subscribe(result => { this.result = result; }); }