Input Mask in ASP MVC Core using DisplayMetadata Provider - asp.net-core

I was trying to find a way to implement Input Mask by passing custom attribute from Model Class in MVC ASP NET Core and built HTML attribute accordingly into HTML element .below is the answer

I would like to share with you on how you apply the Input Mask using DisplayMetadata Provider as it is different than other version.
Here are brief steps more info on this can be find it in this link: In MVC Core Passing custom attribute from Model class to HTML element "e.g.:Input Masking" https://www.codeproject.com/Tips/1243346/In-MVC-Core-Passing-custom-attribute-from-Model-cl
1- Create Custom Attribute e.g.:HTMLMaskAttribute , inherit from Attribute Class
2- Create custom DisplayMetadataProvider by implementing the interface IDisplayMetadataProvider , this provider will read the new attribute from the model class .
3-register CustomMetadataProvider in the startup class of MVC application
4-In Model Class add the new custom attribute "mask" in the property you need to create a mask of it example Phone number.
5- I am using Masked Input Plugin for my example download it and include the jQuery and masked input javascript files to your specific view page or to your _Layout.cshtml page .
6- add this script into your view either _layout.cshtml or specific view :
<script type="text/javascript">
$(function () {
$('[mask]').each(function (e) {
$(this).mask($(this).attr('mask'));
});
});
</script>
7- create the view and include the Property that has an attribute
8- Run the application and notice the html attribute mask has been added for to the property Phone1
<input name="Phone1" class="form-control valid" id="Phone1" aria-invalid="false" type="text" value="(123) 456-7890" mask="(999) 999-9999">

Related

Razor template/component solution that supports child Razor markup

Is there a template/component solution in ASP.NET Core Razor, that supports inner Razor markup?
Here's a use case:
1. Say I have some repetitive markup for example "a div with nice borders, shadows and two buttons at the bottom"
2. Obviously this markup has a common "header" and a "footer" in the HTML code
3. I need to pass arbitrary Razor markup to insert between header and footer. Not just a model object - but some actual markup that will be rendered between header and footer. I can't use foreach because this markup is different every time - it can be text-content, a form, an image, or some complicated Razor-rendered stuff.
Basically I'm looking for a "Surround this Razor with more Razor" templating solution
Something like:
#{
//this function renders my beautiful box
Func<dynamic, IHtmlContent> myFunction = #<div class="relative flex flex-col rounded-2xl border border-gray-200 bg-white p-8 shadow-sm">
#item
</div>;
}
<!-- and then I call it passing some Razor as input -->
#myFunction(
<ul>
<li>#SomeRazorMethod()</li>
</ul>
);
Something like a Layout - but the one I can use multiple times on the same page.
Is there anything like that? This is a pretty common componentizing tool - "wrap my markup with other markup" - that is present in other templating engines (React, Vue, etc), but apparently not in Razor.
Just to be clear: I'm looking for a Razor-based solution, not a C#-based one. So that my header-footer markup stays in markup files (.cshtml), not in C# files that will have hard-coded HTML magic strings.
Based on your example, this might help.
#functions {
public static IHtmlContent MyBox(dynamic item, Func<dynamic, IHtmlContent> template)
{
var html = new HtmlContentBuilder();
html.AppendHtml("<div class='bestcss'>");
html.AppendHtml(template(item));
html.AppendHtml("</div>");
return html;
}
}
#MyBox(null, #<div class='innercss'>#(10 == 12 ? "MyTest Equals" : "No Equal") hello</div>)
And if you like to pass modeldata, it will be:
#MyBox(customerdata, #<div class='innercss'>#(10 == 12 ? "MyTest Equals" : "No Equal") hello #item.FirstName</div>)
I have used some arbitrary if condition for testing.
You can use Partial Pages or Views which are Razor files containing snippets of HTML and server-side code to be included in any number of pages or layouts.
Just like standard Razor pages, partial pages support the #model
directive specifying the type for the partial's data model. All of the
rendering methods have overloaded versions that take a model to be
consumed in the partial.
#Shah's answer got me one step closer to a solution, however, it seems like the the actual question I'm trying to solve is "can I pass Razor markup as an input parameter".
Turns out you can, you just have to put # in front of it:
#{
void MyFunc(Func<object, IHtmlContent> template)
{
<div>#template(null)</div>
}
}
#{ MyFunc(#<div>The ID is: #Model.Id</div>); }
<!-- mind the '#' before the 'div' -->

How to integrate my code into a sitefinity project

We have a sitefinity Customer Portal. Now we need to add MVC pages to it. I understand how to add a page, and how to drag e.g. a list to the page's content. But I don't understand how I can create a controller and other c# code to populate the list and do other custom things. We cannot open the project in Visual Studio, and we have no access to the existing code.
First of all, you must sure your project run success on your local. You can check it by login to back end page.
Then you can create the MVC component like this: (you should create all of this in root/MVC folder)
Create controller first:
[ControllerToolboxItem(Name = "ImportCSV", Title = "ImportCSV", SectionName = "ImportCSV")]
public class ImportCSVController : Controller
{
// GET: ImportCSV
public ActionResult Index()
{
return View();
}
}
SectionName is title of content group for you custom
Title is the title of component
Name is used for code behind
Then you can create the views to show in page: (you have to create the views in MVC/Views/ImportCSV, sitefinity will recognize folder name to map in BE)
<h2>Upload File</h2>
<div class="form-group">
<input type="file" id="dataFile" name="upload" />
</div>
<div class="form-group">
<a onclick="upload()" class="button" id="btnupload">Upload</a>
</div>
You need to get access to the code then, controllers\models need to be compiled. You can get away with a lot directly in a cshtml file though which DOESN'T need to be compiled.
Could you download a new blank SF project that's on your version and start from scratch pointed at your DB? Copy over /App_Data and /ResourcePackages to the new project and just run it. Should work fine, but any page that has a custom widget on it that uses custom code would tank. Sorry I'm just not sure why you don't have the code. Could use JustDecompile to retrieve the actual code for custom widgets too I suppose.

how to show all the errors on a page in one shot (submit button) by client side validation in mvc .net core

I have a page with many required fields. So when I click submit button required validation is firing for the first field then the second then the third and so on...
What I need to do here is , When I click on submit I have to show all errors on a page in one shot.
My requirement is to achieve this only by validating client side.
I am using an .Net core MVC application.
Below is the screenshot of my page
Can I achieve this.. Please help me..
Thanks !!
I can give you an idea to do your job using jquery custom validation.Please refer my solution.
Add custom style class to your required fields.
Example :
<input type="text" class="req-cls" >
Write Jquery function to Check Validation
$(document).ready(function () {
$('#btn1').click(function (e) {
var isValid = true;
$('.req-cls').each(function () {
if ($.trim($(this).val()) == '') {
isValid = false;
$(this).css({
"border": "1px solid red",
"background": "#FFCECE"
});
}
else {
$(this).css({
"border": "",
"background": ""
});
}
});
if (isValid == false)
e.preventDefault();
});
});
See Example here : https://jsfiddle.net/Shalitha/q2n8L9wg/24/
Just add this line in your .cshtml
<div class="validation-summary-valid" data-valmsg-summary="true">
<ul>
<li style="display: none;"></li>
</ul>
</div>
Since you need client side we are talking about JS. But with razor you can validate a few results using the model annotations. For example let's say you have this object.
public class UserCreationVO
{
[Required]
[StringLength(255)]
public string Username { get; set; }
}
Now what you need to do in your frontend (meaning your .cshtml file) is to tell asp.net to use this properties to validate. So for example:
#model UserCreationVO
<form method="post">
<input asp-for="UserName" />
<span asp-validation-for="UserName"></span>
</form>
As you can see above using asp-for is a great way to create validations using your models. Be careful you must pass as a model the object you want to validate. The asp-for tag shows a model property. So you can't pass it in a Viewbag or something. This produces some automatic html and js for you and handles it.
Furthermore you should always validate the result nevertheless in the controller. Because client side validation is for performance reasons and user experience and doesn't offer any kind of security:
public IActionResult CreateUser(UserCreationVO user)
{
if(!ModelState.IsValid)
return your_error;
}
Last but not least: You must include the JQuery unobtrusive validation library. Furthermore if you have some extra requirements like checking if a username exists (Which can't be done without contacting the server) then you can use the [Remote] attribute.
More info and reading about front-end validation with razor: here
How to use a remote attribute: Using remote validation with ASP.NET Core
EDIT:
So generally I advise to use models and create them. As you say policy is required in one form but not in another. What you should do to have a maintanable code where you simply change the attribute of your model and the validation happens you need to create a different VO. For example:
public class CreatePolicyVO
{
[Required]
public string PolicyNumber {get; set;}
}
And another object for example updating:
public class UpdatePolicyVO
{
public string PolicyNumber {get; set;}
}
Because you also need to validate them in the controller. So passing a different object allows you to use ModelState.IsValid and other MVC and razor features. Generally if a field is required in one case and not in another then you need a different model.
First, we need to add the JQuery,jquery.validate & jquery.validate.unobtrusive in our views.
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.16.0/jquery.validate.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.6/jquery.validate.unobtrusive.min.js"></script>
Then in View add required data-* attributes like:
<label for="Name">Name</label>
<input type="text" data-val="true" data-val-length="Length must be between 10 to 25" data-val-length-max="25" data-val-length-min="10" data-val-required="Please enter the name" id="Name" name="Name" value="" />
<span class="field-validation-valid" data-valmsg-for="Name" data-valmsg-replace="true"></span>
<br />
You could see that it has added the several attributes starting with data-*.
The data-* attributes are part of the HTML5, which allow us the add extra information (metadata) to the HTML element.
The Javascript unobtrusive library reads the data-val attributes and performs the client side validation in the browser when the user submits the form. These Validations are done before the form is sent over an HTTP. If there is a validation error, then the request will not be sent.

how to customize sitefinity's default mvc form widget's thank you message as html?

I have created a test form and displayed using sitefinity's default mvc form widget and when submitting the form it displays thank you message(directly as text) without any html. I want to add some html with it so that i can style it as per my liking.
Change the form on the page to use UseAjaxSubmit from the widget designer model. After this go to "\ResourcePackages\Bootstrap\MVC\Views\Form\Index.cshtml" and find this piece of code.
if (Model.UseAjaxSubmit)
{
<h3 data-sf-role="success-message" style="display: none;">
#Model.SuccessMessage
<div>my customized message</div>
</h3>
You can change the rendering directly in the default template but I would recommend you to create a new template for the widget and keep the default one.
The Sitefinity Knowledgebase contains workarounds to override this when using AjaxSubmit or not.
If using AjaxSubmit is not enabled:
Create a new file under the Form folder (again, ResourcePackages > Bootstrap > MVC > Views > Form) with the following name: "Form.SubmitResultView.cshtml"
Use the following to display the styled text:
#Html.Raw(HttpUtility.HtmlDecode(ViewBag.SubmitMessage))
I ended up having to add my Form.SubmitResultView.cshtml under Mvc > Views > Forms and used the following markup as I needed a consistent wrapper div:
<div class="some-class">
#ViewBag.SubmitMessage
</div>

Use TagHelper inside another TagHelper

I have build a custom tag helper that dynamicaly build a form with input tags.
Example
foreach(var foo in foos)
{
htmlOutput += $"<input asp-for='{foo.FieldName}' />";
}
then i want to model bind this, but my custom tag helper output the asp-for attribute instead of model bind it, probably because im trying to use a tag helper inside my custom tag helper. Any way to get around this?