Asp.net Core Razor Pages Post From _layout - c#

What i'm trying to do is change the theme of the application using a check box that is populated as dark or light from the server's session.
I know the theme (Style Sheet) can be changed with JavaScript but that leads to loading the default Bootstrap Style Sheet then the dark one which causes the screen to flicker.
What I need to do is return the css from the server thought a post method like below.
<div>
<form id="theme-switcher" method="post">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" asp-for="IsDark" id="theme" />
<label class="custom-control-label" for="theme">Theme</label>
</div>
<button id="change" type="submit" class="btn btn-primary">Change</button>
</form>
</div>
The code above can be in a view component or a partial view but I can not seem to find a way to post the from.
_Layout.cshtml
#{
bool isDark = HttpContext.HttpContext.Session.GetBoolean("IsDark");
}
<!-- Custom styles -->
#if (CultureInfo.CurrentUICulture.Name == "ar-LB")
{
if (isDark)
{
<link rel="stylesheet" type="text/css" href="~/css/site-dark-rtl.css">
}
else
{
<link rel="stylesheet" type="text/css" href="~/css/site-rtl.css">
}
}
else
{
if (isDark)
{
<link rel="stylesheet" type="text/css" href="~/css/site-dark.css">
}
else
{
<link rel="stylesheet" type="text/css" href="~/css/site.css">
}
}
What I've tied so far is partial views and view components but as far as I've found partial views can not have code behind with OnPost (when adding #page to the partial view I get view data can not be null although the model and the view data are set) and view components can not call methods.
What approach should I use ?

You can post to different routes, regardless of where you currently are. So assuming you have a Razor page SwitchTheme.cshtml with a code-behind that switches the theme on POST, then you can adjust your <form> tag to post to that page:
<form asp-page="/SwitchTheme" method="post">
<!-- … -->
</form>
Note the use of the asp-page tag helper to generate the action attribute with a link to the page.
For changing things like the design, which doesn’t directly have some page content you want to display, you could also use a simple controller that makes the change and then redirects back. Then, you would use the asp-action and asp-controller tag helpers instead:
<form asp-controller="Utility" asp-action="SwitchTheme" asp-route-returnUrl="#Context.Request.Path" method="post">
<!-- … -->
</form>
public class UtilityController : ControllerBase
{
[HttpPost]
public IActionResult SwitchTheme([FromForm] bool isDark, string returnUrl)
{
// switch the theme
// redirect back to where it came from
return LocalRedirect(returnUrl);
}
}

Related

Can a view selectively populate sections that appear outside the view in ASP.NET mvc?

I'm making a simple site with bootstrap and .net core mvc (v3.0). Because most of the pages reuse the bootstrap container, I decided to put that in the layout file, so that I wouldn't be repeating the same setup everywhere.
This has the downside that if a view needs fixed elements, those end up getting fixed to the container, not the viewport.
I'm wondering if it's possible to call some sort of syntax inside the view.cshtml file that could cause a section to be rendered in the _Layout.cshtml file (sorry if this has been answered, but I wasn't sure what to search for).
For instance
_Layout.cshtml
#using Microsoft.Extensions.Hosting
#inject Microsoft.AspNetCore.Hosting.IWebHostEnvironment _environment
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>#ViewData["Title"]</title>
</head>
<body>
#* this div only gets rendered based on logic inside the view*#
<div id="conditionalViewDiv">
</div>
<div class="content container-fluid pl-0 pr-0 moveable" id="containerMain">
<main role="main">
#RenderBody()
</main>
</div>
#RenderSection("Scripts", required: false)
</body>
</html>
and then in SomeView.cshtml
#{
ViewData["Title"] = "title";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#MadeUpRenderCommand("conditionalViewDiv")
#*other view stuff*#
Thank you for any help.
According to the docs, View components are intended anywhere you have reusable rendering logic, similar to partial views, but they're much more powerful. The main difference is when you use partial view you still have dependency on controller while in View Component you don't need a controller. So there is a separation of concern.
A view component is a C# class that provides a partial view
with the data that it needs, independently from the parent view and the action that renders it.
Good enlightening examples can be found, particularly:
https://www.c-sharpcorner.com/article/working-with-view-components-in-asp-net-core-mvc/
https://jakeydocs.readthedocs.io/en/latest/mvc/views/view-components.html
Hope this helped.

How do I call a function in my controller from a button in my .cshtml-page?

I'm trying to create a dashboard/graphical interface for managing purposes. How can I create buttons that call certain functions from a controller? It's in ASP.NET CORE 3, using the MVC-pattern.
What I want to do in the application is executing c# code by calling a method from my Index.cshtml page and passing parameters.
I've tried multiple solutions, namely those that state that the view and controller are synced with the controller function looking for the "equally named" view but it just doesn't work.
Edit: Found the solution: I needed to specify both the controller and ActionResult.
<form action="Home/Change" method="post">
<input type="text" name="DoorID" placeholder="Guid.." />
<br />
<input type="submit" value="Post" />
</form>
I was apparently not smart enough to read the countless tutorials.
Thanks for the help!
If you want to send a piece of data after the button click to the server, you should create a form in your view and a post action in your controller. However, if you don't want to post any data and you want to simply do something after button click, creat a get action in your controller and navigate to that action path using button click event. Finally, you can return the same page at your action and do what you want before hand.
Use [httpGet("path")] attribute on top of any public function in your controller to Mark it as action. Then you can invoke it in HTML using something like this <a asp-action="path">sth</a>
since you only wants to trigger a function on a btn click and pass some data i recommend you to make an ajax call to the back-end using java script or jquery is the more effective way.
it will look like this
$('#btn').click(function () {
$.post( "your action url ", { name: "John", time: "2pm" } )
.done(function(data)
{
// in case your action return some data it will be in the "data" variable
});
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- you need to have jquery -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<title>Document</title>
</head>
<body>
<input type="button" id="btn" value="click me ">
</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");
}

Apply CSS on button in ASP.net MVC 3

I started experimenting with MVC 3. And I'm stuck with applying the style of an input-button.
Is it possible to apply Css in the View? The code I gave is located in the View.
<input id="newSubItem" type="button" onclick="location.href='javascript:void(0);'" value='New Subitem' /><br/>
Did you try
<input id="newSubItem" class="myCSSClass" type="button" onclick="location.href='javascript:void(0);'" value='New Subitem' />
You have to put link in the view to your css page :
<link href="#Url.Content("~/CSSPAGE.css")" rel="stylesheet" type="text/css" />
And then you can apply any class you want,for example
<input id="newSubItem" class="CSSClass1" type="buttononclick="location.href='javascript:void(0);'" value='New Subitem' />

MVC .NET CSS not picked up by the View

I am working on a MVC2 site and am having issues getting my objects on my views to inherit the css classes.
Here is my helper object and CSS that is saved in the Site.css which is linked in the master page.
This also works fine if I put the CSS in a tag on the masterpage.
<%= Html.ListBox("ExpenseItems", (System.Web.Mvc.SelectList)ViewData["ExpenseDefinitions"], new { #class = "optionlist" })%>
.optionlist
{
width:100px;
height:100px;
}
Browser HTML:
..
<link href="../Content/Site.css" rel="stylesheet" type="text/css" />
..
<select class="optionlist" id="ExpenseItems" multiple="multiple" name="ExpenseItems">
<option value="1">Test</option>
</select>
Figured it out... Can't apply the style to the list.
Some reason, you need to apply it to a div then apply to the control in CSS.
example:
CSS:
.optionlist select
{
width:100px;
height:100px;
}
<div class="optionlist">
... Lisbox
</div>
when you link your css file that way, and if you are browing in in a page with a url like this http://yoursite.com/MyPage/Content/Article of course the css file will not be found since it goes this way.
css file mapped in `../Content/Sites.css`
Page is `/MyPage/Content/Article`
css real content is placed in `/Content`
when the parser looks for the css it looks in `/MyPage/Content/Site.css`
which is not where it where it is.
My suggestion is add a base url to your css link
<%
string baseUrl = "http://" + Request.Url.Host + (Request.Url.Port != 80 ? ":" + Request.Url.Port.ToString() : "");
$>
<link href=<%=baseUrl%>/Content/Site.css rel="stylesheet" type="text/css" />
Don't put " in href of the link tag

Categories