How to remove required attribute in MVC4, although that has been made required in model - asp.net-mvc-4

I am not able to do the same thing with string properties. In the below code, I want to remove the validation of the 'Last Name' and make it optional.
[Required(ErrorMessage = "Required")]
[Display(Name="Last Name")]
public string LastName { get; set; }

You can add following java-script to your view and it will to remove the required rule for LastName although it has been made required in model.
$("#LastName").rules("remove", "required");
Thanks!

If you want to ModelState to be valid then try this:
ModelState["LastName"].Errors.Clear();
if (ModelState.IsValid)
{
// your logic
}
if you want to disable clientside validations then :
#Html.EnableClientValidation(false);
Note: this will disable all the client side validations.

You can disable client side validation for specific field with this
<form method="post">
// to disable client-side validaiton for model.SomeValue
#{ Html.EnableClientValidation(false); }
#Html.TextBoxFor(model => model.SomeValue)<br />
#{ Html.EnableClientValidation(true); }
<input type="submit" />
</form>
or you can omit ModelState Error for specific field in controller side with this
ModelState.Remove("SomeValue"); // to omit SomeValue Validation Error
if(ModelState.IsValid)
{
//Do some stuff, eventually redirect elsewhere
}

Related

NavLink updating URL but does not reloading page in Blazor

I have a ProjectBase.razor page that is used to create, view & edit projects. The following routes all take you to this page:
/project/view/{projNum}
/project/create/
/project/edit/{projNum}
I also have a Navlink in my navigation menu that allows you to create a new project:
<NavLink class="nav-link" href="/Project/Create" Match="NavLinkMatch.All" >
<span aria-hidden="true">New Project</span>
</NavLink>
If I click on that link while on the view/edit features of the same page, the URL changes to "/Project/Create," but the page itself doesn't refresh or reload. Is there a way to force this through the NavLink? Or do I need to add an OnClick function to do this?
Create and use the OnParametersSetAsync task in your code block for the page. This event will fire when parameters change.
#code
protected override async Task OnParametersSetAsync()
{
// This event will fire when the parameters change
// Put your code here.
}
Yes, using something like Microsoft.AspNetCore.Components.NavigationManager and its NavigateTo function with forceLoad set to true will accomplish what you're looking for.
Of course yes, this will require you to set up an onclick function, but this is the way I ended up accomplishing something similar for a site-wide search page which never technically had its URL change outside of the query string search value I was passing it.
That being said, there may be a decent way of doing it with only NavLinks. I'll update my answer when I'm not on mobile.
In my component I had already overridden OnInitializedAsync in order to make an API call to get my data.
My solution looks like this:
protected override async Task OnInitializedAsync()
{
// Make your API call or whatever else you use to initialize your component here
}
protected override async Task OnParametersSetAsync()
{
await OnInitializedAsync();
}
I had same problem. Solution I have is...
Create new page
#page "/project/create/"
<ProjectBase></ProjectBase>
That's it! remove #page directive for(/project/create/) from ProjectBase page
Everything will work as expected... now do it for all pages you have.
In your case you have to make below changes as mention by Rod Weir, I am just extending the answer.
/project/view/{projNum}
/project/create/
/project/edit/{projNum}
For above query parameter you have to define [Parameter] in your code.
[Parameter]
public string projNum {get;set;}
Then add method
protected override async Task OnParametersSetAsync()
{
var projectDetail = await getProjectDetails(projNum); // ProgNum will change as it get changes in url, you don't have to do anything extra here.
}
Force page to reload will land you in some other problems, it will get the correct result but the page behavior will change. There are other components on the page like header/left Nav/ etc these will not changes if they are dynamic. It will force you to make changes and hanlde force reload in all the components. Also user experience is affected.
Hope this help.
That is by design.The page itself doesn't refresh or reload because the <NavLink> does not send request to the server (F12 to check) and it redirect to the same page on the client, so nothing updates.
If you enter those URLs in the browser,they will send requests and then refresh page.
A workaround is that you could display different content based on the current route.
#page "/project/view/{projNum}"
#page "/project/create/"
#page "/project/edit/{projNum}"
#using Models
<h3>ProjectBase</h3>
#if (projNum == null)
{
<EditForm Model="#createModel" OnValidSubmit="#HandleValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
<InputText id="name" #bind-Value="createModel.Name" />
<button type="submit">Create</button>
</EditForm>
}
else
{
<EditForm Model="#exampleModel" OnValidSubmit="#HandleValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
<InputText id="name" #bind-Value="exampleModel.Name" />
<button type="submit">Submit</button>
</EditForm>
}
#code {
[Parameter]
public string projNum { get; set; }
private ExampleModel createModel = new ExampleModel();
private ExampleModel exampleModel = new ExampleModel();
protected override void OnInitialized()
{
exampleModel.Name = projNum;
}
private void HandleValidSubmit()
{
//your logic
Console.WriteLine("OnValidSubmit");
}
}

using must in fluentValidation

I am using FluentValidation for the server side validation. Now I want to call a function using must.
This is the form code snippet :
<form method="post"
asp-controller="Category"
asp-action="SaveSpecification"
role="form"
data-ajax="true"
data-ajax-loading="#Progress"
data-ajax-success="Specification_JsMethod">
<input asp-for="Caption" class="form-control" />
<input type="hidden" asp-for="CategoryId" />
<button class="btn btn-primary" type="submit"></button>
</form>
What changes should I make to the code below to call function SpecificationMustBeUnique ?
public class SpecificationValidator : AbstractValidator<Specification>
{
public SpecificationValidator()
{
RuleFor(x => new { x.CategoryId, x.Caption}).Must(x => SpecificationMustBeUnique(x.CategoryId, x.Caption)).WithMessage("not unique");
}
private bool SpecificationMustBeUnique(int categoryId, string caption)
{
return true / false;
}
}
Tips: 1 - The combination of CategoyId and Caption should be unique
2 - Validation is not done when submitting the form(the validation just not running when submit the form)
The tricky part is deciding which property should be validated when the validation rule applies to a combination of values on different fields. I usually just close my eyes, and point to one of the view model properties and say "this is the property I'll attach the validator to." With very little thought. FluentValidation works best when the validation rules apply to a single property, so it knows which property will display the validation message.
So, just pick CategoryId or Caption and attach the validator to it:
RuleFor(x => x.CategoryId)
.Must(BeUniqueCategoryAndCaption)
.WithMessage("{PropertyName} and Caption must be unique.");
The signature for the BeUniqueCategoryAndCaption method would look like:
private bool BeUniqueCategoryAndCaption(Specification model, int categoryId)
{
return true / false;
}
Note: I guessed that the CategoryId property is an int, but you will need to make sure the categoryId argument to BeUniqueCategoryAndCaption is the same type as the CategoryId property in your view model.

asp-validation-for tag helper is not working for server side validation errors

CustomerEntryModel
[Required]
public String FirstName { get; set; }
CustomerController.cs
[HttpGet]
[Route("Get")]
public IActionResult Get()
{
CustomerEntryModel model = new CustomerEntryModel();
return View("CustomerEntry", model);
}
[HttpPost]
[Route("Update")]
public ActionResult Update([FromForm]CustomerEntryModel model)
{
if (!ModelState.IsValid)
{
return View("CustomerEntry", model);
}
return null;
}
CustomerEntry.cshtml
#addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
<form asp-controller="Customer" asp-action="Update" method="post">
<input type="text" asp-for="FirstName" />
<span asp-validation-for="FirstName" />
<input type="submit" value="Submit" />
</form>
I do not include the jQuery validation libraries, so the validation occurs on the server side. Now, when I submit the page with first name empty, the update action gets executed and I receive back the same view, but without any error.
Instead of <span asp-validation-for="FirstName" /> tag helper, if I use the html helper #Html.ValidationMessageFor(m => m.FirstName) I get the required error for first name.
As per my understanding TagHelper extends the behavior of traditional HtmlHelper to provide HTML friendly development experience. That means, something that works with HtmlHelper has to work with it's TagHelper counterpart.
After the ModelState.IsValid call, I CAN see Controller.ModelState (instance of ModelStateDictionary), having the error for FirstName property. However, the TagHelper isn't able to bind it.
You can find the MVC6 validation tag helpers detail here,
http://www.davepaquette.com/archive/2015/05/14/mvc6-validation-tag-helpers-deep-dive.aspx
I suggest try changing this:
<span asp-validation-for="FirstName" />
like this:
<span asp-validation-for="FirstName"></span>
maybe it will make a difference

kendo editor not responding after multiple requests to the same page in IE

I have a very weird bug. I have a page on MVC that displays two editors and gets passed a model with the value for both editors. The model is as follows:
public class BulletinsModel
{
[AllowHtml]
[Display(Name = "Some Bulletin")]
public string SomeBulletin { get; set; }
[AllowHtml]
[Display(Name = "Other Bulletin")]
public string OtherBulletin { get; set; }
}
I then, defined a view which receives this view model and maps it to two kendo editors.There is also some javascript code to make a post to update the information.
#model BulletinsModel
<div id="settings">
<div class="form-horizontal">
<div class="form-group">
#Html.LabelFor(m => m.SomeBulletin, new { #class = "col-md-6 text-left" })
#(Html.Kendo().EditorFor(m => m.SomeBulletin).Encode(false).Name("Some_Bulletin"))
#Html.LabelFor(m => m.OtherBulletin, new { #class = "col-md-6 text-left" })
#(Html.Kendo().EditorFor(m => m.OtherBulletin).Encode(false).Name("Other_Bulletin"))
</div>
</div>
</div>
My code for my action method that renders this view is as follows (nothing fancy):
[HttpGet]
public PartialViewResult Index()
{
ViewBag.ActiveSectionName = "Bulletins";
var bulletinModel = GetBulletinsModel();
return PartialView("_Bulletins",bulletinModel);
}
However, my issue is that after hitting the Index action a couple of times, the editors become non responsive and I cannot edit the information on them. This only happens on IE, as I have not been able to replicate the issue in other browsers.
EDIT: I have just noticed that the editor is frozen. In order to be able to edit what's inside of the editor I need to click on any option of the toolbar to make it responsive once again. Why is that?
Turns out that the issue is happening with IE as detailed in this post:
Adding, removing, adding editor -> all editors on page become read only in IE. The problem is with the iframes inside the editor. I was loading my page with an Ajax request to which I had to add the following code before making the request to make it work.
function unloadEditor($editor) {
if ($editor.length > 0) {
$editor.data('kendoEditor').wrapper.find("iframe").remove();
$editor.data('kendoEditor').destroy();
}
}
unloadEditor($('#myEditor'));

Error: Cannot convert lambda expression to type 'string' because it is not a delegate type

Error:Cannot convert lambda expression to type 'string' because it is not a delegate type
I am getting this error when I am trying to add in cshtml page in mvc4.
at line Customer Name: #Html.TextBox(m => Model.CustomerName)
Could anyone explain what is its meaning and why it comes here?
Code is
#model DataEntryMvcApplication.Models.Customer
#using (Html.BeginForm())
{
<p>Customer Name: #Html.TextBox(m => Model.CustomerName)</p>
<p>ID:#Html.TextBox(m=>Model.CustomerId)</p>
<input type="submit" name="Custtomer" />
}
and this is model class;
namespace DataEntryMvcApplication.Models
{
public class Customer
{
public string CustomerId { get; set; }
public string CustomerName { get; set; }
}
}
You'll need Html.TextBoxFor instead of Html.TextBox:
#model DataEntryMvcApplication.Models.Customer
#using (Html.BeginForm())
{
<p>Customer Name: #Html.TextBoxFor(m => m.CustomerName)</p>
<p>ID:#Html.TextBoxFor(m => m.CustomerId)</p>
}
The difference between the two is explained here
Model doesn't exist in the linq expression which is the parameter of #Html.TextBox(...). The m represents the Model and you need to use that variable to access the correct properties, like here:
<p>Customer Name: #Html.TextBoxFor(m => m.CustomerName)</p>
<p>ID:#Html.TextBoxFor(m=>m.CustomerId)</p>
Try like this,
#model DataEntryMvcApplication.Models.Customer
#using (Html.BeginForm())
{
<p>Customer Name: #Html.TextBox(m => m.CustomerName)</p>
<p>ID:#Html.TextBox(m=>m.CustomerId)</p>
<input type="submit" name="Custtomer" />
}
Just spent ages trying to solve this. After restoring old pages and making changes one by one, it appears the line causing the problem is:
<img src="~/images/Captcha/#ViewBag("CaptchaName")" />
I think it must not like attempts to access the view bag? Whatever, commenting this out solved the problem.