How to make this ASP.NET Core Model Validation work on client-side? - asp.net-core

In my ASP.NET Core 1.1.1 app the following Model Validation is not working. I think the issue is related to me not properly adding validation scripts in Main View below.
Scenario:
I click on a button on Main View that calls a partial view.
I enter all correct values, in partial view and submit the form (in partial view), the form successfully gets submitted and all the values are correctly entered into SQL server db.
I then intentionally enter a string, say, abc into the input box for price (that is of nullable type float) and submit the form. A client side error does NOT show up even (the javascript is enabled on my Chrome browser). Hence, Form gets submitted to the server where ModeState.IsValid, as expected, is false in the POST action method.
Question: Why client-side validation (as shown in step 3) above is not working and how we can make it work?
Note: All the css and javascripts were added and configured by default by VS2017 when the project was created. So I think scripts are all there and I may not be calling them correctly on the views - but that's just an assumption.
MyViewModel
public class MyViewModel
{
public int FY { get; set; }
public byte OrderType { get; set; }
public float? Price { get; set; }
....
}
Main View
#model MyProj.Models.MainViewModel
...
<div>
<button type="submit" name="submit"...>GO</button>
</div
#section scripts
{
<script>
$(document).ready(function () {
....
$('.tab-content').on('click', '.BtnGO', function (event) {
....
$.ajax({
url: '#Url.Action("SU_AddCustOrder", "MyContr")',
data: { ....},
contentType: 'application/json',
dataType: 'html',
type: 'GET',
cache: false,
success: function (data) {
if (BtnVal == 'AddOrderBtnGo')
$('#menuAP').html(data);
else if ....
error: function (....){
alert(...);
}
});
});
MyContrController:
[HttpGet]
public IActionResult AddCustOrder(int Order_id)
{
....
return PartialView("~/Views/PartialsV/MyPartialView.cshtml", myVM);
....
}
[HttpPost]
public IActionResult AddCustOrder(MyViewModel model)
{
....
if(ModelState.IsValid)
{
....
}
....
}
Partial View
....
<div class="form-group">
<label asp-for="Price"></label>
<div class="col-md-10">
<input asp-for="Price" class="form-control"></input>
<span asp-validation-for="Price" class="text-danger"></span>
</div>
</div>
....
<button type="submit" name="submit"...>Add Order</button>
UPDATE
_layout.cshtm file
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>#ViewData["Title"] - Test</title>
<environment names="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment names="Staging,Production">
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>
#RenderSection("styles", required:false)
</head>
<body>
<header>
<div class="container navbar navbar-inverse navbar-fixed-top text-center">
</div>
<div class="container nav nav-pills" style="margin-top:4px;background-color:cornsilk;">
#await Component.InvokeAsync("Welcome")
</div>
</header>
<div class="container body-content">
#RenderBody()
<hr />
<footer class="text-center">
<a asp-controller="Misc" asp-action="AccessibilityStatement" class="text-center text-muted">Accessibility Statement</a>
</footer>
</div>
<environment names="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
<environment names="Staging,Production">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/bootstrap.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal">
</script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
</environment>
#RenderSection("scripts", required: false)
#RenderSection("css", required:false)
</body>
</html>

I see. If you go and open Shared folder inside Views folder you will find a file called _ValidationScriptsPartial.cshtml that contains the validation scripts.
Now the first thing to do is to add validation attributes such as [Required] to your view model.
Than in Main View add #{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } before <script>.
After you add the html of the partial view in this line $('#menuAP').html(data);, find the form and call $.validator.unobtrusive.parse() like the following
if (BtnVal == 'AddOrderBtnGo') {
$('#menuAP').html(data);
var $form = $('#menuAP').find('#your-form-id-here');
$.validator.unobtrusive.parse($form);
}

Related

How to set focus for InputRadio / InputRadioGroup in Blazor?

I want to set the focus on the InputRadioGroup but it appears it doesn't have the ElementReference attribute unlike the other Blazor built-in form components. Should I just extend the InputRadioGroup and add the ElementReference or is there another way to set focus on the InputRadio or InputRadioGroup?
You could refer to the sample below to focus on the InputRadio.
Vehicle.cs
namespace BlazorApp1.Model
{
public class Vehicle
{
public string Name { get; set; }
}
}
file1.js
window.jsfunction = { focusElement: function (id) { const element = document.getElementById(id); element.focus(); } }
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>BlazorApp1</title>
<base href="/" />
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="css/app.css" rel="stylesheet" />
<link href="BlazorApp1.styles.css" rel="stylesheet" />
<script src="file1.js"></script>
</head>
<body>
<div id="app">Loading...</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
Reload
<a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.webassembly.js"></script>
</body>
</html>
Index.razor
#inject IJSRuntime js
#page "/"
<div>
<h4> vehicle Selected - #vehicle.Name </h4>
<EditForm Model="vehicle">
<InputRadioGroup #bind-Value="vehicle.Name" >
#foreach (var option in rdOptions)
{
<InputRadio Value="option" id=#option #onfocus="alrt" /> #option <br />
}
</InputRadioGroup>
<br>
<input Id="idPassWord" Type="password" />
<button #onclick="clickOK">Set Focus</button>
</EditForm>
</div>
#code{
BlazorApp1.Model.Vehicle vehicle=new BlazorApp1.Model.Vehicle(){Name = "auto"};
List<string> rdOptions = new List<string> { "car", "bus", "auto" };
private async void clickOK()
{
await Focus("car");
}
private void alrt()
{
Console.WriteLine("Element focused");
}
public async Task Focus(string elementId)
{
await js.InvokeVoidAsync("jsfunction.focusElement", elementId);
}
}
Output:
In the above code example, I am generating the InputRadio on the page which has the OnFocus event. While we try to set the Focus on the InputRadio using the JS code. OnFocus event gets fired and displays the message in a browser console. This proves that InputRadio is getting focused.
Further, you could modify the code as per your own requirements.
After some investigation, seems like the ability to focus for InputRadio/InputRadioGroup was removed due to some prior issues. They now returned the focus after I raised the issue, and it will be included to .NET 7.

Bootstrap Alerts in Asp.net Core Razor Pages

How to configure bootstrap alerts in asp.net core razor pages.
<div class="alert alert-success">
<strong>Well done!</strong> You successfully read this important alert message.
</div>
As far as I know, if you want to show the alert, you could try to use jquery to achieve your requirement, you could add class in into the alert div. You could use ajax to call the razor page's onpost method and check the response if the response is true then you could alert success if not you could alert fail message.
More details, you could refer to below example codes:
#page
#model IndexModel
#{
ViewData["Title"] = "Home page";
}
#{
Layout = null;
}
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<div class="alert alert-success alert-dismissible fade" id="buttonAlertSuccess">
<strong>Well done!</strong> You successfully read this important alert message.
</div>
<div class="alert alert-success alert-dismissible fade" id="buttonAlertFail">
<strong>False</strong> You failed read this important alert message.
</div>
<button class="btn btn-secondary" id="modalButton" type="submit">Button</button>
#Html.AntiForgeryToken()
<script>
$(function () {
$("#modalButton").click(function () {
$.ajax({
type: "post",
url: "index",
beforeSend: function (xhr) {
xhr.setRequestHeader("CSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
success: function (response) {
if (response == "True") {
$("#buttonAlertSuccess").addClass('in');
} else {
$("#buttonAlertFail").addClass('in');
}
}
});
})
});
</script>
Post method:
public ActionResult OnPost() {
return new JsonResult("True");
}
Notice:
If you want to use ajax call ,you should set the CSRF-TOKEN settings in the startup.cs ConfigureServices method like below:
services.AddAntiforgery(o => o.HeaderName = "CSRF-TOKEN");
Result:
Please find the complete code and try if it helps
<!DOCTYPE html>
<html>
<head>
<title>Bootstrap Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<div id="alert_div" style="margin: 0 0.5%; -webkit-box-shadow: 3px 4px 6px #999;" class="alert-success">
<strong>Well done!</strong> You successfully read this important alert message.
</div>
</body>
</html>

Is there any solution about asp.net core mvc switch route without refresh page like angular route reuse strategy

i just want to achieve the following results,switch route without refresh page
supplement:
i want to keep the page state
You can achieve this function partial view.
Here is a simple demo for your reference:
HomeController:
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult FirstTab(string param)
{
return PartialView("_FirstTab",param);
}
}
Index.cshtml:
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
$(function () {
$("#tabs").tabs();
});
</script>
<div id="tabs">
<ul>
<li>Page1</li>
<li>Page2</li>
</ul>
<div id="tabs-1">
#Html.Partial("_FirstTab", "Page1")
</div>
<div id="tabs-2">
#Html.Partial("_FirstTab", "Page2")
</div>
</div>
_FirstTab.cshtml partial view:
#model string
<h1>This is the #Model Tab</h1>
<input id="Text1" type="text" />
Test result:

PartialView getting data only for one View

Hey guys i'm using asp mvc4 for building a site,im having trouble in Views
First of all i have my _Layout View calling a partialView for header and my partial View is getting data from a model in to fill some data in the header,
It's working by the way just in the Main (index) view but moving to another views just call the Partial view without getting data from database.
Hope i explained Well :D
_layout View
#model MvcApplication1.Models.SchoolInfo
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>#Html.DisplayFor(model => model.SiteName)</title>
<!-- Bootstrap Core CSS -->
<link href="~/Content/Template/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom CSS -->
<link href="~/Content/Template/css/business-casual.css" rel="stylesheet">
<!-- Fonts -->
<link href="http://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="http://fonts.googleapis.com/css?family=Josefin+Slab:100,300,400,600,700,100italic,300italic,400italic,600italic,700italic" rel="stylesheet" type="text/css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
<body>
<header>
<section id="login">
#Html.Partial("_LoginPartial")
#if (Request.IsAuthenticated)
{
#Html.Partial("_SiteHeaderPartial")
}
</section>
</header>
#RenderBody()
#if (Request.IsAuthenticated){
<footer>
<div class="container">
<div class="row">
<div class="col-lg-12 text-center">
<p>Copyright © Your Website footer</p>
</div>
</div>
</div>
</footer>
}
<!-- jQuery -->
<script src="~/Scripts/Template/js/jquery.js"></script>
<!-- Bootstrap Core JavaScript -->
<script src="~/Scripts/Template/js/bootstrap.min.js"></script>
<!-- Script to Activate the Carousel -->
<script>
$('.carousel').carousel({
interval: 5000 //changes the speed
})
</script>
_SiteHeaderPartial
#model MvcApplication1.Models.SchoolInfo
<div class="brand">#Html.DisplayFor(model => model.SchoolName)</div>
<div class="address-bar">Country | Address : #Html.DisplayFor(model => model.SchoolAddress) | 011 #Html.DisplayFor(model => model.SchoolPhone)
Index and About views are the same (empty).
If your not seeing the details in the About.cshtml view, its because you have not passed a SchoolInfo model to that view (or the model is not populated with the data). However a layout should not include a model declaration (unless its a base model from which all views that use that layout derive).
Remove #model MvcApplication1.Models.SchoolInfo from the layout and instead of #Html.Partial("_SiteHeaderPartial"), use
#Html.Action("SiteHeader", "yourControllerName")
where SiteHeader() is a a controller method that gets your data and returns a partial view, for example
[ChildOnlyAction]
public PartialViewResult SiteHeader()
{
SchoolInfo model = ... // populate your model
return PartialView("_SiteHeaderPartial", model);
}
Sife note: You also need to remove <title>#Html.DisplayFor(model => model.SiteName)</title> or replace it with (say) <title>#ViewBag.Title</title> and in each view, pass the value to the partial using #{ ViewVag.Title = someValue; }

How to get a rating value in asp.net mvc4?

I am new asp.net mvc4 with entity frame work, I have designed rating in cshtml file,Pls help me to get a rated value in Controller. Thanks in advance.
This is my cshtml code for rating
{
#{
ViewBag.Title = "Index";
}
<h2>Index rating</h2>
<h2>rating</h2>
#*<form method="post" id="signin" action="#Url.Action("rating", "Rating")">*#
#if (Request.IsAuthenticated)
{
<form method="post" id="signin" action="#Url.Action("rating", "Rating")">
<p>
#DateTime.Now
</p>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="~/Scripts/jquery.js"></script>
<script type="text/javascript" src="~/Scripts/rating.js"></script>
<link rel="stylesheet" type="text/css" href="~/Styles/rating.css" />
<script type="text/javascript">
$(function () {
$('.rating').rating();
$('.ratingEvent').rating({ rateEnd: function (v) { $('#result').text(v); } });
});
</script>
<input type="text" class="ratingEvent rating5" #*id="result"*# value="rating" />
<div><b id="result">5</b> start(s)</div>
<p> </p>
</form>
}
}
This is my Controller code
{
[HttpGet]
public ActionResult rating(int ratedvalue)
{
using (var db = new Project.Models.EntitiesContext())
{
var value= new Project.Models.Tbl_Rating();
var rat = db.Tbl_Rating.FirstOrDefault(u => u.Rating == ratedvalue);
value.Rating = Convert.ToInt32(rat);
return View();
}
}
}
}
try like this
View:
<form method="post" id="signin" action="#Url.Action("rating", "Rating")">
**YOUR CODE**
<input type="text" class="ratingEvent rating5" name="rating" value="rating" /> //Add name attribute
<input type="submit" />
</form>
Controller:
public ActionResult rating(FormCollection form)
{
int ratedvalue=form["rating"]
}