When I click submit on view, the system redirects to a new view. If validation fails, the system redirects to the same page highlighting the fields. However, I also require the system to show a label with the error message.
<label for="label6" style="color:red; font-weight:normal !important; visibility: hidden">
The Corporate Email, FEIN or SSN does not match.<br /><br />
<span style="margin-left: 10%"></span>The following might be the case:<br />
<span style="margin-left: 12%"></span>- The Corporate Email entered is wrong. Please check the Corporate Email.<br />
<span style="margin-left: 12%"></span>- The FEIN entered is wrong. Please check the FEIN.<br />
<span style="margin-left: 12%"></span>- The SSN entered is wrong. Please check the SSN.<br />
<span style="margin-left: 12%"></span>- Please verify whether FEIN or SSN entered during registration.<br />
<span style="margin-left: 16%"></span>If you have registered using FEIN please submit using FEIN.<br />
<span style="margin-left: 16%"></span>If you have registered using SSN please submit using SSN.<br />
</Label>
Can someone help me with this.
I don't think you want to do it like that. Why tell them what the error might be when you can tell them what the error actually is?
In your view, after each #Html.EditorFor put a #Html.ValidationMessageFor.
#Html.TextAreaFor(a => a.EmailID)
#Html.ValidationMessageFor(a => a.EmailID)
#Html.TextAreaFor(a => a.Password)
#Html.ValidationMessageFor(a => a.Password)
If your model state is invalid and you return to the view, the validation messages are automatically displayed for the invalid fields.
Going further, you can get the validation to be done using JavaScript in the browser, so that if the data is invalid the error message(s) will be displayed without needing a trip back to the server.
Simply add the following to the end of your view:
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
(This assumes your site is based on the standard ASP.NET MVC template, and that you view uses a layout view. If not, you may have to do a bit of tweaking to get the correct JavaScript files.)
WARNING: Never rely solely on browser validation checking. It is there as a benefit to users so they get errors reported slightly faster. However, it is very easy for hackers to bypass browser checking, so always check the model state on the server as well.
If you want exactly that content, then in your controller, when the model is invalid, put
ViewBag.InvalidModel = true;
Then in your view put
#if(ViewBag.InvalidModel)
{
<!-- Your label here-->
}
In controller
public ActionResult Index()
{
if (ModelState.IsValid)
{
//do something
return Redirect("/yournewpage");
}
if (!someChecks)
{
ModelState.AddModelError("", "Your custom error");
}
if (!someChecks2)
{
ModelState.AddModelError("", "Your custom error 2");
}
return View();
}
You can use in view
<p>
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<p>
Related
I have created a simple admin panel to access a administration page. i type /admin on my url and get this page.
<form>
<center>
<br>
<br>
<label>Username:</label>
<input type="password" id="username" #bind-value="adminusername" />
<br>
<br>
<label>Password: </label>
<input type="password" id="password" #bind-value="adminpassword" />
<br>
<br>
<button #onclick="#authenticatecredentials" id="login" style="background-color:green;" class="btn btn-primary btn-medium">Login</button>
<br>
<br>
<br>
</center>
</form>
#code {
public string adminusername { get; set; }
public string adminpassword { get; set; }
public void authenticatecredentials()
{
if (adminusername == "myusername" && adminpassword == "mypassword")
{
NavigationManager.NavigateTo("/Ka9fVDrE7vc", true);
}
else
{
jSruntime.InvokeVoidAsync("invalidcredentials");
}
}
}
invalidcredentials is an javascript alert:
function invalidcredentials() {
alert("Invalid Credentials");
}
When i run the application, sometimes it logs in successfully sometimes it does not. When it doesn't, i get a (?) next to my url on my Admin login page:
I need a simple hardcoded "login" page that will direct to the admin panel link. No SQL or Models.
Your form is doing a submit which reloads the page instead of using Blazor's router. Prevent this by adding #onclick:preventDefault (or use EditForm instead):
<button #onclick="#authenticatecredentials" #onclick:preventDefault id="login" style="background-color:green;" class="btn btn-primary btn-medium">Login</button>
Then, change your call to NavigateTo. By passing true as the second parameter you are again bypassing Blazor router. You can pass false or omit the argument:
NavigationManager.NavigateTo("/Ka9fVDrE7vc");
A note on security:
I don't know if your app is wasm or server, but either way it is not secure, even for internal use only. there is a reason you are putting a "login" page so making it so easy to bypass could come back to bite you.
If this is a wasm app then the problem is even worse. Anyone can download the application dll from the browser tools and decompile it, seeing the username and password, or just seeing the obfuscated url which can be accessed without login:
The button inside the form, has the default value of the attribute type=submit, if not specified. To fix this, set the type to button:
...
<button type='button'.../>
...
.NET Core v6
MVC Web App with Entity Framework Core
I scaffolded a database table and it created a "db context", then I scaffolded default Controller and Views.
On the home page, I want to create a search box where you put in the primary key, or id. On submit, I want the value passed to the default Edit controller. Essentially, I want someone to be able to pull up a single record to Edit, if they know the primary key (id).
Here is what I have for a search box
<form asp-controller="MyTables" asp-action="Edit">
<p>
PIN: <input type="text" name="id" />
<input type="submit" value="Find" />
</p>
</form>
Here is the default Edit method inside the Controller.
// GET: MyTables/Edit/XYZ
public async Task<IActionResult> Edit(string id)
{
if (id == null)
{
return NotFound();
}
var MyTable = await _context.MyTables.FindAsync(id);
if (MyTable == null)
{
return NotFound();
}
return View(MyTable);
}
When I run this, it doesn't work, but I don't know how to set it up. How can I make this work? The only way I've been able to pull a record is by adding method="get" to the form, but then it creates a URL structure using "id" as a parameter like this localhost/MyController/Edit?id=XYZ. This structure won't work because I'm unable to save the record when I've navigated to the page in this way.
I appreciate any pointers or ideas.
Thank you
EDIT AFTER COMMENTS:
It has been suggested that I could go ahead and use the method="get", thereby selecting the correct record. The URL would be in this format: localhost/MyController/Edit?id=XYZ. A proposed solution is to fix my POST action to be able to save the record when using such URL paths. I'm not sure why, but it will only save right now if the URL path is in this format: localhost/MyController/Edit/XYZ (no parameter ?id =).
Here is a version of my default POST Edit action in the controller.
// POST: MyTables/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(string id, [Bind("...,...,...,...,...,...,PrimaryKeyField")] MyTable myTable)
{
if (id != myTable.PrimaryKeyField)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(myTable);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MyTableExists(myTable.primaryKeyField))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(MyTable);
}
In the Edit view, to initiate the POST action, here's some of the Edit Form markup:
#model myApp.Models.MyTable
...
<form asp-action="Edit">
...
<div class="form-group">
<label asp-for="PrimaryKeyField" class="control-label"></label>
<input asp-for="PrimaryKeyField" class="form-control" />
<span asp-validation-for="PrimaryKeyField" class="text-danger"></span>
</div>
...
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
The reason I'm saying it won't Save is when I click Submit on the Edit form, it brings up this HTTP error:
This localhost page can’t be found. No webpage was found for the web address: https://localhost:7020/MyTables/Edit
HTTP ERROR 404
In the Edit View, I added a reference to the Model.
#model myApp.Models.MyTable
In the form, I added a Tag Helper.
<form asp-action="Edit" asp-route-id=#Model.PrimaryKeyField>
This is working.
I noticed in the URL pattern of /Edit/XYZ, the form's asp-action uses this pattern. I noticed with the URL pattern of /Edit/?id=XYZ, the form's action uses /Edit with NO ID. Therefore, I figured out a way to add the id to the form's action by using the asp-route-id tag helper. The form submits the data properly now.
I have a simple feedback form on our website. When users enter html in the page, they should get a validation error message. But they don't. The exception is thrown and caught in:
void Application_Error(object sender, EventArgs e)
{
...
}
The exception caught here is:
A potentially dangerous Request.Form value was detected from the
client
at System.Web.HttpRequest.ValidateString(String value, String
collectionKey, RequestValidationSource requestCollection)
Here is the Asp.net MVC markup:
<form action="<%=Url.Action("Create") %>" method="post" class="data-entry-form">
<fieldset class="comment">
Your thoughts:
<div class="editor-field">
<%= Html.TextAreaFor(model => model.Comment, 10, 2, new { placeholder="your message" }) %>
<%= Html.ValidationMessageFor(model => model.Comment) %>
</div>
<br />
E-mail address (optional)
<div class="editor-field">
<%= Html.TextBoxFor(model => model.Email, new { placeholder="you#youremailaddress.com" }) %>
<%= Html.ValidationMessageFor(model => model.Email) %>
</div>
<input type="submit" value="Send" />
</fieldset>
</form>
and here is the generated html:
<form action="/feedback/Create/" method="post" class="data-entry-form">
<fieldset class="comment">
Your thoughts:
<div class="editor-field">
<textarea cols="2" id="Comment" name="Comment" placeholder="your message" rows="10">
</textarea>
</div>
<br />
E-mail address (optional)
<div class="editor-field">
<input id="Email" name="Email" placeholder="you#youremailaddress.com" type="text" value="" />
</div>
<input type="submit" value="Send" />
</fieldset>
</form>
And here is the controller code:
[HttpPost]
public ActionResult Create(Feedback feedback)
{
if (ModelState.IsValid)
{
FillFeedbackObject(feedback);
feedbackRepository.AddFeedback(feedback);
return View("SuccessMessage", new SuccessMessageModel("Thanks for your message!"));
}
return View(feedback);
}
I also have <add key="ClientValidationEnabled" value="true" /> in the appSettings section of the web.config file and I am including jquery.validate.js. So both client side and server side validation fail.
What is wrong?
It's not technically a Model's error, that's why you cannot handle it with Model.IsValid code statement.
If you actually allow html to be submitted in this field or want to sanitize submitted value on server you may annotateComment property of your model with [AllowHtml] attribute. Also, if you want to notify user that they cannot include tags in the text, you may add an error to ModelState during feedback parsing on server side with ModelState.AddModelError() method.
Obviously, leaving request validation in place has it's advantages, and you're correct disabling request validation shouldn't be taken lightly. But there's no graceful way to handle this exception in ASP.NET because it happens so early in the pipeline. It's the actual framework protecting you from yourself.
You can use the Application_Error event that you pointed out in your original post. The come up with some code like:
protected void Application_Error(object sender, EventArgs e)
{
var exception = Server.GetLastError();
if (exception is HttpRequestValidationException)
{
// use Response.Redirect to get the user back to the page, and use session/querystring to display an error
}
}
Try adding the [ValidateInput(false)] attribute to your controller action method.
Source: http://msdn.microsoft.com/en-us/library/system.web.mvc.validateinputattribute.aspx
Edit: If you still want to validate, you should encode the input before sending to the server, for example using HttpUtility.HtmlEncode. The reason the validation blocks the code is because it could be malicious. By encoding it you can allow it to pass through and still have validation enabled. However you may need to change your validation rules/attributes to account for the encoding. In case it wasn't clear before, this option requires validating on the server side once you get to the controller, adding an error to the ModelState as needed, and returning the same view or partial view as needed in case of errors.
With MVC 3 and above you can use the AllowHtml attribute with the property that can contain some html
I have a simple MVC application that retrieves DB Server, database, username and password from the user to store in an XML file. I want to add a "Test Connection" button to the screen and have it execute a method on the controller called TestConnection. The problem is the TestConnection method resets all the information on the screen when clicked since the View is being returned with no model. (because a GET operation is occurring). Here is my code:
From the Controller (named FrameworkConfigurationController.cs)
public ActionResult TestConnection()
{
return View("Index");
}
[HttpPost]
public ActionResult TestConnection(FrameworkConfigurationViewModel viewModel)
{
// TODO: Test will occur here
viewModel.DbConnectionMessage = string.IsNullOrEmpty(viewModel.DatabaseName) ? "Connection unsuccessful" : "Connection successful";
return View("Index", viewModel);
}
From my View (FrameworkConfiguration/Index):
#model Framework.ViewModels.FrameworkConfigurationViewModel
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>FrameworkConfigurationViewModel</legend>
<div class="editor-label">
#Html.LabelFor(model => model.ServerName)
</div>
#* Edited for brevity *#
<button type="submit" onclick="location.href='#Url.Action("TestConnection")'">
Test Connection</button>
#Html.ValueFor(model => model.DbConnectionMessage)
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to Dashboard", "Index", "Home")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Admittedly, I am new to MVC programming. I'm coming from a Silverlight/MVVM background so the concept is not foreign to me...the disconnected nature of web programming is. I've followed some tutorials out there, but none of them seem to cover this type of thing - every example is contrived. I know how to do this with webforms and code-behind, but I would like to accomplish this with MVC.
Is there some way to "force" the POST operation instead of GET? I was under the impression that
<button type="submit">
accomplished that. Perhaps the implementation of the onclick I have written isn't correct. I am sure this is HTML 101 stuff, but I can't seem to find a simple answer to this.
Thanks for any help you can offer,
Jason
Why not have the Test Connection button trigger an Ajax action to call the controller, and display the result?
That way you avoid submitting your entire page.
In case you're not familiar with the details, here's a good overview on getting started with Ajax and MVC 4
http://ofps.oreilly.com/titles/9781449320317/ch_AJAX.html
I'm rendering some input controls dynamically. I wrote a method like this
public override MvcHtmlString GetActionControl(HtmlHelper<ItemDetailsViewModel> helper)
{
return
helper.EditorFor(A => A.Triage.ProcessNumber) +
helper.ValidationMessageFor(a => a.Triage.ProcessNumber, "*")
}
And I'm calling this from the main CSTHML file like this:
<!-- Render Action Controls for each possible action -->
#foreach (IActionControl iac in WorkflowActionControls.GetActionControls(Model.WorkflowItem.CurrentState))
{
<div id="#("div" + iac.ControlName)" class="ui-corner-all ui-widget ui-widget-content" style="margin-top: 24px; padding: 15px;">
#iac.GetActionControl(this.Html)
</div>
}
Notice that I'm passing the current HtmlHelper to the GetActionControl() method.
Problem is, the generated output is only:
<input class="text-box single-line" id="Triage_ProcessNumber" name="Triage.ProcessNumber" type="text" value="" />
Ie, no "extended" validation fields, and no validation . Aditionally I've discovered that the helper.ValidationMessageFor() method returns NULL.
However, If I put the editor and the validationMessage on the .cshtml directly everything works like a charm:
#Html.EditorFor(a => a.Triagem.ProcessNumber)
#Html.ValidationMessageFor(a => a.Triagem.ProcessNumber, "*")
What am I doing wrong here? Shouldn't the end result of calling HtmlHelper.EditorFor be the same? I'm sorry if this is a lame question but there isn't much information on generating HTML markup dynamically in regards to MVC 3.
I've checked the common pitfalls and everything is OK: validation enabled on web.config, the model class has the proper validation attributes, etc.
Any help would be greatly appreciated :)
PS: I've simplified the pasted code and ommited the form.
I don't know if this will help you, but validation is rendered when Html.ViewContext.FormContext is not null. When i had same problem, i just initialized form context with new FormContext(); and it worked