Razor View IsAuthenticated not working as expected - c#

I have created a simple MVC application that is using the .Net Membership Provider that is supplied with the new project.
I am trying to get the tabs to show correctly. I might not understand this right but here's my code:
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
</head>
<body>
<div class="page">
<div id="header">
<div id="title">
<h1>Suburban Customer Portal</h1>
</div>
<div id="logindisplay">
#Html.Partial("_LogOnPartial")
</div>
<div id="menucontainer">
<ul id="menu">
#if (Request.IsAuthenticated)
{
<li>#Html.ActionLink("ChangePassword", "ChangePassword", "Account")</li>
}else {
<li>#Html.ActionLink("Logon", "Logon", "Account")</li>
<li>#Html.ActionLink("Register", "Register", "Account")</li>
}
<li>#Html.ActionLink("ContactUs", "ContactUs", "Home")</li>
</ul>
</div>
</div>
<div id="main">
#RenderBody()
</div>
<div id="footer">
</div>
</div>
</body>
</html>
At this line:
#if (Request.IsAuthenticated)
I am trying to show the right tabs pending on if they are already authenticated. This is always coming out as true...
How should I be doing this? I apparently am not doing it the right way...
Thanks again!

I think you should use
#if(User.Identity.IsAuthenticated)

Well, your question is not very clear, but Request.IsAuthenticated in this line:
#if(Request.IsAuthenticated)
checks if the request has data about an authenticated user. If true, you link will be shown.
In your specific case the Change Password link will only be shown if the user is logged in.
It looks correct.
For the tabs to be hidden, that is, for Request.IsAuthenticated = false you must first logout so that the cookies that store login information are cleared from the user browser.

Related

Can we consume a Blazor component as a Web Component within a regular non-Blazor HTML page?

Can we render a Blazor component as an independent DOM fragment, or somehow else consume it as a standard Web Component within a vanilla HTML/JS page?
This might be a naive question from the Blazor architectural standpoints. I am not a Blazor expert by far, but I think it can be a useful technique for incremental "brownfield" modernization of legacy web applications. I'm surprised this doesn't appear to be officially supported.
To illustrate, consider this simple web component example, which renders a custom element <date-info>:
// define a custom web component
customElements.define("date-info", class DateInfo extends HTMLElement {
constructor() {
super();
// create an "open" (vs "closed") shadow DOM,
// i.e., accessible to the outside JavaScript
this.attachShadow({ mode: "open" });
}
async connectedCallback() {
console.log(`${this.constructor.name}.${this.connectedCallback.name} called`);
// get the content from the server,
// this could be a Blazor component markup
try {
const response = await fetch("https://worldtimeapi.org/api/ip");
const data = await response.json();
const content = new Date(data.utc_datetime).toString();
this.shadowRoot.innerHTML = `<span>${content}</span>`;
}
catch(e) {
console.error(e);
const info = document.createTextNode(e.message);
this.shadowRoot.appendChild(info);
}
}
});
<!-- use the web component -->
<p>Current time: <date-info/></p>
Now, instead of fetching https://worldtimeapi.org/api/ip, I'd like to fetch and render a detached markup for a Blazor/Server component, e.g.:
#* this is a Blazor component *#
<p>#(DateTime.Now)</p>
Moreover, I'd expect this markup to remain functional and dynamic, i.e., the client-side DOM events and the server-side updates for this Blazor component to further propagate both ways, through the life cycle of the wrapping web component.
It's surely possible to make it a Blazor #page and load it into an iframe, but I'm rather looking to render it as a part of the outer page's DOM.
So far, I've come across this:
Apparently, that wasn't one of Blazor design goals back in 2018:
https://github.com/dotnet/aspnetcore/issues/16033.
Later Steve Sanderson created an (unofficial) library to test Blazor components in isolation, which in theory can be used to get a standalone Blazor component markup: https://stackoverflow.com/a/60457390/1768303.
Is it the best approach to tackle this problem, so far?
MS has addressed this limitation, but the solution requires .Net 6.
https://github.com/aspnet/AspLabs/tree/main/src/BlazorCustomElements
This was done by the man himself, Steve Sanderson.
In the meantime you can mix the old cshtml with razor components.
I use this approach to maintain the same graphic layout between the two systems.
An example, the following file is _Layout.cshtml used by Identity.
I've used various Blazor components via static rendering:
#using Microsoft.AspNetCore.Hosting
#using Microsoft.AspNetCore.Mvc.ViewEngines
#inject IWebHostEnvironment Environment
#inject ICompositeViewEngine Engine
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
#using Project.Server.Shared
<!DOCTYPE html>
<html>
<head>
<component type="typeof(MainLayoutHead)" render-mode="Static" />
</head>
<body>
<app>
<div class="container main">
<component type="typeof(MainLayoutTopImages)" render-mode="Static" />
<div class="row navmenu-row">
<div class="col-md-12 bg-dark navmenu-col">
<component type="typeof(NavMenu)" render-mode="Static" />
</div>
</div>
<div class="row content pt-4 pb-0 mt-0">
<div class="col-md-12">
<div class="row">
<div class="col-md-12">
#*Required for GDPR.*#
<partial name="_CookieConsentPartial" />
</div>
</div>
<div class="row body-row">
<div class="col-md-12 body-col">
#RenderBody()
</div>
</div>
</div>
</div>
<component type="typeof(MainLayoutFooter)" render-mode="Static" />
</div>
</app>
<script src="~/Identity/lib/jquery/dist/jquery.min.js"></script>
<script src="~/Identity/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/Identity/js/site.js" asp-append-version="true"></script>
#RenderSection("Scripts", required: false)
</body>
</html>
The MainLayoutHead, MainLayoutFooter and NavMenu are regular Blazor components.
Not sure if this helps but you can definitely do it from a server side page (I'll delete this answer if it doesn't). Here's a test page that renders all three standard "pages" inside a cshtml page with server side content. You need to actually forget the "page" concept in Blazor. EVERYTHING is a Component. Pages are just components with a Page custom attribute.
The problem with this setup is that as soon as you refresh the page you restart the three components and you lose any scoped data.
#page "/test"
#namespace StackOverflow.Answers.Pages
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
#{
Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>StackOverflow.Answers</title>
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
<link href="StackOverflow.Answers.styles.css" rel="stylesheet" />
</head>
<body>
<div class="m-2 p-s bg-light">
<h3>A Normal Razor Page</h3>
<p>
Lots of server side rendered junk
</p>
<component type="typeof(StackOverflow.Answers.Shared.SurveyPrompt)" render-mode="ServerPrerendered" />
</div>
<div class="m-2 p-s bg-info">
<h3>A Normal Header</h3>
<p>
Lots More server side rendered junk
</p>
<component type="typeof(StackOverflow.Answers.Pages.Counter)" render-mode="ServerPrerendered" />
</div>
<div class="m-2 p-s bg-light">
<h3>A Normal Header</h3>
<p>
Lots More server side rendered junk
</p>
<component type="typeof(StackOverflow.Answers.Pages.Counter)" render-mode="ServerPrerendered" />
</div>
<div class="m-2 p-s bg-light">
<h3>Yet Another Normal Header</h3>
<p>
Lots More server side rendered junk
</p>
<component type="typeof(StackOverflow.Answers.Pages.FetchData)" render-mode="ServerPrerendered" />
</div>
<div class="m-2 p-s bg-light">
<h3>Yet Another Normal Header</h3>
<p>
Lots More server side rendered junk
</p>
<component type="typeof(StackOverflow.Answers.Pages.FetchData)" render-mode="ServerPrerendered" />
</div>
<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for details.
</environment>
Reload
<a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.server.js"></script>
</body>
</html>

How do I link pure html form to controller in C#

I have searched for quite some time on how to link pure html to mvc 4 controllers and came up empty. I am unsure of what I'm doing wrong, though I know there will be many errors in my code since I'm new to this.
I have a simple web page that I'm trying to link to a controller but I'm getting an error when ever I hit submit. I'm also using Bootstrap (not really used in this example but the links are there), but I'm sure that's not the source of this error and that it's server side. The error I'm getting is
0x800a1391 - JavaScript runtime error: 'Button1_Click' is undefined
The HTML page is actually an aspx because I wanted to do easy conversions of small websites over from java.
Here is the example page (It's been edited many times with different variations of buttons to submit):
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>arrggghh</title>
<meta name="generator" content="Bootply" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link href="/css/bootstrap.css" rel="stylesheet">
<link href="/css/styles.css" rel="stylesheet">
<!--[if lt IE 9]>
<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<div id="wrapper">
<div class="navbar navbar-default navbar-static-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="index.html">Page</a>
</div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li>Home</li>
</ul>
<ul class="nav navbar-nav navbar-right"></ul>
</div><!--/.nav-collapse -->
</div>
</div>
<div id="header">
</div>
<div class="content-form-blank2">
<div>
<table class="margin">
<tr>
<td><h4>Press button.</h4></td>
</tr>
</table>
</div>
<form id="myform" action="Home" method="post">
<input type="submit" onclick="Button1_Click" />
</form>
</div>
</div>
<div class="form-navigation-bottom">
</div>
<!-- /.container -->
<!-- script references -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<script src="/js/bootstrap.min.js"></script>
</body>
</html>
And this is my example controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using arrgg.code;
namespace arrgg.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
protected void Button1_Click()
{
new arrggOut();
}
}
}
The error isn't as important as me understanding how to link pure html to the controller. Thanks in advance... if anyone has the required time to write a book about everything I'm doing wrong.
I will soon start using helpers and reading up more about asp.net and MVC
You need to post from your form submission to the correct route e.g. /Home/DoSomething. Then, in your controller, provided the route has been established, you will be mapped through to the DoSomething method in your Home controller. Do not write it as Button1_Click(). When you click that button, it should simply submit the form with the appropriate URL as its action, unless you need to do something prior to submission e.g. client side validation. Then, the controller can handle it and do something meaningful with it, described by the method name.
View:
<form id="myform" action="/Home/DoSomething" method="post">
<input type="submit" />
</form>
Controller:
namespace arrgg.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult DoSomething()
{
// Or whatever you require here...
return View();
}
}
}
Further info: http://www.asp.net/mvc/overview/older-versions-1/controllers-and-routing/creating-an-action-cs
Button1_Click is JavaScript event. Call controller action from this event. Add this text to the bottom of the html:
<script>
function Button1_Click() {
$.post('/Home/Button1_Click', {}, function(res) {
});
}
</script>
To avoid JavaScript change html. Instead of:
<form id="myform" action="Home" method="post">
<input type="submit" onclick="Button1_Click" />
</form>
Write:
<form id="myform" action="/Home/Button1_Click" method="post">
<input type="submit" />
</form>
And change controller action. It must be public and return ActionResult:
[HttpPost]
public ActionResult Button1_Click()
{
return RedirectToAction("/Home/Index");
}

Jquery Scripts does not work on Partial View's first time load but work with Ajax call MVC C#

I have a problem in loading scripts on first time load of view in ASP.NET MVC, the scripts are present on Partial View but these scripts are not called when page is being loaded first time.
But when I append the same partial view second time using Ajax call, the scripts load perfect on the view and components present earlier on the view appended by the partial view also work perfect.
Here I little further discuss my problem in detail that when same scripts I call via _Layout view, then these scripts does not work on partial view, and When I put the same scripts on Partial view also then the problem arises of scripts called two times and my functions are called twice.Actually I am using SignalR scripts and due to 2 times referencing of scripts one time on _layout View and 2nd on Partial view my SignalR functions are called twice and my all code logic ruins.
This is my Home view code:
#model IEnumerable<SmartKids.Lib.Core.ViewModels.FileMediaAlbumsVM>
#{
ViewBag.Title = "Home";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="profile-body">
#*#Html.Partial("ModalMessages")*#
<div class="row">
#Html.Partial("_Messages")
</div>
<div class="row infinite-scroll">
<input type="hidden" value="" name="clientScreenWidth" id="clientScreenWidth" />
#Html.Partial("_AlbumRow", Model)
</div>
<div id="loading" class="text-center">
<i class="fa fa-spinner fa-2x fa-spin"></i>
</div>
</div>
#section scripts{
<script src="~/Scripts/infiniteScroll.js"></script>
<script type="text/javascript">
var moreRowsUrl = "/Album/Home"; //the URL to your ActionMethod
$(window).scroll(scrollHandler);
</script>
}
and This is my Main _Layout code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title - Smart Kids</title>
<link rel="shortcut icon" href="favicon.ico">
<link rel='stylesheet' type='text/css' href='//fonts.googleapis.com/css?family=Open+Sans:400,300,600&subset=cyrillic,latin'>
<!-- CSS Global Compulsory -->
<link href="~/Content/plugins/bootstrap/css/bootstrap.css" rel="stylesheet" />
<link rel="stylesheet" href="~/Content/css/headers/header-default.css" />
<!-- CSS Customization -->
<link rel="stylesheet" href="~/Content/css/custom.css" />
<style type="text/css">
.fancybox-custom .fancybox-skin {
box-shadow: 0 0 50px #122;
}
</style>
#RenderSection("metaTags", false)
#Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class="wrapper">
<!--=== End Header ===-->
<div class="container" id="main">
<div class="row">
<div class="col-md-12">
#RenderBody()
</div>
</div>
</div>
</div>
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
<script src="~/signalr/hubs"></script>
<script src="~/Scripts/albumSignalR.js"></script>
#RenderSection("scripts", required: false)
</body>
</html>
Now I have no scripts in Partial view and this is my Partial View code:
<div class="widget-extra margin-bottom-15">
<div class="timeline">
<ul class="timeline-list">
<li>
<a href="#Url.Action("HomeAlbum", "Album", new { aId = item.AlbumId })">
<picture class="thumbnail img-responsive">
<source media="(min-width: 480px)" srcset="#Url.Content(filepath_mobile), #Url.Content(filepath_mobile) 2x">
<source srcset="#Url.Content(filepath_small), #Url.Content(filepath_small) 2x">
<img src="#Url.Content(filepath_mobile)" alt="#item.Title">
</picture>
</a>
</li>
</ul>
</div>
</div>
Kindly suggest me some solution to this, what I am doing wrong or what needs to be fixed.
why dont you move the closing script
tag within the closing }
#section scripts{
<script src="~/Scripts/infiniteScroll.js"></script>
<script type="text/javascript">
//$(function () {
// $("div#loading").hide();
//});
var moreRowsUrl = "/Album/Home"; //the URL to your ActionMethod
$(window).scroll(scrollHandler);
</script>
}

jQuery Tabs Errors

I am trying to jQuery tabs in C#. Here is the script sources and stylesheet which I included:
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />
<link rel="stylesheet" type="text/css" href="Styles/jquery-ui.css" />
<script type="text/javascript" src="Scripts/jquery-1.10.2.js"></script>
<script type="text/javascript" src="Scripts/jquery-ui.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#reportTabs").tabs();
});
</script>
And here is where I set up my jQuery tabs:
<div id="reportTabs">
<ul>
<li>By Region</li>
<li>Execution Status Report</li>
<li>Due in 30 Days</li>
<li>Due in 30-90 Days</li>
<li>By Service Area</li>
</ul>
<div id="statusDiv" runat="server">
</div>
<div id="exeDiv" runat="server">
</div>
<div id="dueDiv" runat="server">
</div>
</div>
But somehow when I try to run the page, it tells me an error message which is: mismatching fragment identifier. I wonder which part went wrong?
Thanks in advance.
Change the HTML and try, hopefully it should work, I guess mainContent_ in href is playing culprit
<div id="reportTabs">
<ul>
<li>By Region</li>
<li>Execution Status Report</li>
<li>Due in 30 Days</li>
<li>Due in 30-90 Days</li>
<li>By Service Area</li>
</ul>
<div id="statusDiv" runat="server">
1
</div>
<div id="exeDiv" runat="server">
2
</div>
<div id="dueDiv" runat="server">
3
</div>
<div id="rangeDiv" runat="server">
4
</div>
<div id="areaDiv" runat="server">
5
</div>
</div>
Demo: http://jsfiddle.net/TLB79/
Please check external resources for JS and CSS URL

How would I create a dynamic login button in MVC3

I have this code:
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
</head>
<body>
<div id="header">
<div id="header-inside">
<div id="logo"></div>
<div id="top-menu">
Home | About | Contact |
</div>
</div>
</div>
<div id="content">
#RenderBody()
</div>
</body>
</html>
I want to add a login button there that will detect whether or not the user is logged in, and if the user is it will turn into "logout". I am using Membership Services so I would use MembershipUser
If you have your Request object you can use Request.IsAuthenticated(MSDN docs here) which will work regardless of how you manage your users behind the scenes, as long as it plugs into the system ASP .NET provides.
Example:
#if(Request.IsAuthenticated){
<div id="logout_button"/>
} else {
<div id="login_button"/>
}
You can use Request.IsAuthenticated to detect whether a user is logged in.
<%= Page.User.Identity.IsAuthenticated %>
or
<% Request.IsAuthenticated %> should do the trick
Here's a snippet based on _LogOnPartial.cshtml from default project template:
#if(Request.IsAuthenticated) {
using (Html.BeginForm("LogOff", "Account"))
{
<input type="submit" name="login" value="Log Off" />
}
}
else
{
#:[ #Html.ActionLink("Log On", "LogOn", "Account") ]
}

Categories