Email form in footer to disappear after submit - asp.net-mvc

Im new to .Net MVC, and im for learning purposes making a simple e-mail newsletter signup form in my footer.
#using (Html.BeginForm("details", "Home", FormMethod.Post))
{
<div class="form-group form-inline">
<label class="margin20">Sign up for newsletter</label>
#Html.TextBoxFor(Model => Model.Email, new { id = "input1", Class = "form-control", Style = "display:inline-block; max-width:200px", Placeholder = "Example#Example.com", type = "email" })
<button type="submit" disabled class="btn btn-default" style="display:inline-block" id="emailSignup">Signup</button>
</div>
}
Currently the form works just fine (I can type in my email, and i receive a confirmation mail after submitting).
When the user submits the email, the user is redirected to another page. However, i want this form to work on the same page, so that after the submit button is pressed, it says something like "thank you for subscribing" instead of moving to new view.
Im thinking, that the easy way to come around this would be to make a jQuery script that hides the email form and unhides a div that says "Thank you for signing up"
However, i want to do this in MVC manners, so what would be "most" correct to do? #RenderSection could be an option i guess?

Typically, it's done with simple flags, based on the model state - i.e. whether the e-mail has been sent or not. For example (very rough code);
#if (emailHasBeenSent)
{
<div class="polite-message"> Thanks for signing up! </div>
}
else
{
<div class="form-group form-inline"> your sign up code </div>
}
I'm fairly new to MVC too, but this is what I've seen from other people's code at work!

Related

MVC/ASP.NET: Client side validation not working

EDIT: Consider this whole question replaced by this one:
ASP.NET/MVC: Knockout-binding preventing client-side validation from being performed?
Working in ASP.NET/MVC, I’m having great trouble getting the (unobtrusive or even non-unobtrusive) client side validation to work. (Yes again, but this time for different reasons as it appears.)
NB: The EDITS towards the bottom of the post are important, esp. EDITS 2 and 3.
Problem is, client side validation does absolutely nothing (see below), even though all ingredients seem to be in place. I’ve read through quite a few questions and answers here on Stack Overflow, and it seems everything is done correctly in my project, but still it doesn’t work. What am I missing?
In my Web.config file (the one in the root folder, not the one in the View folder), I’ve explicitly enabled the client side validation:
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
And all the relevant Javascript files are there, in the right order and loading correctly (and I’ve made no changes to them obviously). I’ve included them in bundles, in BundleConfig:
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate.js", "~/Scripts/jquery.validate.unobtrusive.js"));
I add these bundles in my View (well actually in the shared _Layout.cshtml parent view):
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/bundles/bootstrap")
#Scripts.Render("~/bundles/knockout")
And in the generated source code for the View these scripts (and a few others) appear as follows:
Which, as far as I can tell, is correct. (I also use the jQuery as well as knockout extensively in other places in the same View.) Also, no loading errors in the browser console.
Then in my ViewModel, I have this annotated property Email (among others):
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
// some other properties…
}
And this is the corresponding code in my View:
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Email, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Email)
</div>
</div>
Which generates the following source code (click to enlarge):
Which also seems correct, as far as I can tell.
But then when I type something that’s evidently not a valid email-address in the input field, and make the field lose focus (by jumping to the next field), NO ERROR MESSAGE appears. Neither in the summary, nor the specific error message for the email field itself. As seen here:
(The little red square is the .field-validation-valid element that should contain the error message, but doesn't. For testing purposes I had decorated this element with a red border.)
Also, when I press the submit button, the input fields are simply submitted to the server action method (which then correctly determines that the inputs are not valid). But in fact, with client side validation enabled, the submit shouldn’t happen unless client side validation succeeds. But well, that’s basically the whole issue: client side validation simply doesn’t happen, despite the correct HTML being generated (presumably!).
EDIT 1:
And here is the HTML/Razor for the whole form:
#model Treinen2.Models.RegisterViewModel
#{
ViewBag.Title = "Register";
}
#using (Html.BeginForm("Register", "Account", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h4>Create a new account.</h4>
<hr />
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Email, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Email)
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Password, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.ConfirmPassword, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.ConfirmPassword, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Register" />
</div>
</div>
}
This is in a shared View called Register.cshtml, which -- depending on certain conditions -- gets displayed by calling #Html.Partial("Register") from the home view Index.cshtml. [I'm kind of trying to build a single page API application, as an exercise, so everything is included in the homepage (Index), and all navigation happens client side (with the obvious exception of the submit of the "Register" button itself, which gets sent to the server Action method, at least for now). And with obviously only one part ('page') of Index.cshtml being displayed at any one time, for which I use knockout binding.]
EDIT 2:
OK, I've noticed the following: If I put the same form in Index.cshtml, and also add the same model to that Index view, then client-side validation works perfectly. It's only on the partial view that it fails to work. Which suggests that I could simply stop using the partial view, and instead simply include its content on Index.cshtml, as tested. On the other hand, I still don't understand WHY using the partial view for the register form wouldn't work too. (With this new information, I may have to ask the question anew in a different form, but don't have the time right now...) [/EDIT 2]
EDIT 3:
Seems I'm edging closer to understanding the root cause of the problem. Because now I have the validation working with the form on the Index view... BUT it stops working as soon as I put the whole form inside a DIV-element that is bound by a Knockout attribute data-bind="If: ....." So that seems to be the essence of the problem: the interaction between client-side validation and Knockout binding. The Knockout binding, which in and of itself works fine, seems to prevent the validation from being performed. Although I still don't understand why that should be the case. [/EDIT 3]
So, what am I missing? Any constructive suggestions appreciated, will check back in a few hours.

Uncaught Error: Nothing handled the action 'edit' - Correct controller name to put the action

First of all,I am new to ember.I have a "show" handlebar inside "templates/orders/show.hbs" . The form submit action in this handlebar always returning "Uncaught Error: Nothing handled the action 'edit'. If you did handle the action, this error can be caused by returning true from an action handler in a controller, causing the action to bubble." . I have the edit action defined in controllers/orders.js. Am i placing the edit action in wrong file. If so, what would be the correct place to have the "edit" action.
Handlebar(show.hbs):
<form class="form-horizontal" {{action "edit" this on="submit"}}>
<div class="control-group">
<div class="control-label">
<label>Name</label>
</div>
<div class="controls">
{{input value=name type="text"}}
</div>
</div>
<div class="control-group">
<div class="control-label">
<label>Age</label>
</div>
<div class="controls">
{{input value=fury type="text"}}
</div>
</div>
<button type="submit" class="btn">submit</button>
</form>
controller file (orders.js):
export default Ember.ObjectController.extend({
actions: {
edit: function(){
console.log('EDIT - Entered');
}
}
});
Thanks!
As it was pointed out, your question is a bit vague as to how you're rendering your template.
First, make sure you have the Ember inspector installed. There are versions for Chrome and Firefox, and likely other browsers. This will make debugging your Ember application a lot simpler. With the Inspector installed and open, navigate to the "View Tree" and you should be able to figure out which controller is the active controller for your template.
With the syntax:
{{action "myAction"}}
The action will bubble to the controller that is currently responsible for the template. Additionally, if your template is rendered within a view and you want the view to handle the action and not the controller, you can specify:
{{action "myAction" target="view"}}

Fixings Cross Site Scripting (Reflected) in ASP.Net MVC

I have been using the Zed Attack Proxy (ZAP) to test a new application being developed. The App is ASP.NET MVC4 based using the standard HTML helpers where ever possible.
ZAP has identified the following alert:
Cross Site Scripting (Reflected)
GET: localhost:65227/CashReceipt?SearchText=javascript%3Aalert%281%29%3B
On this page we have a list of receipts and a search box whereby a user can search by receipt number.
When this page is called using the link above, the following Razor builds the relevant part of the page:
#using (Html.BeginForm("Index", "CashReceipt", FormMethod.Get, new { #class = "form-inline", #role = "form" }))
{
<div class="form-group">
<label class="hidden-label" for="SearchText">Search For</label>
#Html.TextBoxFor(m => m.SearchText, new { #class = "form-control input-lg", #placeholder = "Receipt Number" })
</div>
<input type="submit" value="Search" class="btn btn-primary btn-lg" />
}
the HTML generated is:
<input class="form-control input-lg" id="SearchText" name="SearchText" placeholder="Receipt Number" type="text" value="javascript:alert(1);" />
The page rendered appears as:
This does not result in an actual alert box being displayed within the browser, just the text is reflected back.
Is this an XSS issue that needs to be resolved? If so, how?
No it is not an XSS issue since the javascript alert is not executed. Razor Html helpers properly encode and decode text to stop this from happening by default.

How can I programmatically trigger client side validation set up by a Razor view?

I have a little Ajax application where I use Razor views to initially generated HTML form segments that I later read and write from with knockout.js. Although I am doing no non-Ajax action requests, I use Razor to generate the HTML so I enjoy automatic generation of jQuery Validation attributes. E.g. in my single page, I render a hidden form like this:
<section id="person-detail">
#Html.Action("EditPartial", "Person")
</section>
The EditPartial action returns a partial view that looks a lot like this:
#using (Html.BeginForm())
{
<fieldset>
#Html.HiddenFor(model => model.Id, new { data_bind = "value: id" })
<div class="editor-label">
#Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.FirstName, new { data_bind = "value: firstName" })
#Html.ValidationMessageFor(model => model.FirstName)
</div>
<p>
Update
Delete
</p>
</fieldset>
}
Because I'm never actually posting the form, and due to some unknowns, despite all properties on my Person model being marked with the Required attribute, I see no sign of client side validation. What must I do to trigger this validation when my save button is clicked?
suppose your form has a class 'main':
$('form').submit(function() {
var $form = $('form.main');
$form.valid();
});

ASP.NET MVC3 - displaying "updated" model values for summary display before form submission

I have a view named AddEditModule that is used, believe it or not, for Adding or Editing a module. The workflow is kind of a wizard using navigation buttons that hide/show div's.
I've got a ViewModel called AddEditModuleModel (say that 10 times fast). In steps 1 & 2 I'm displaying my fields using various EditorFor's. In step 3, I'd like to use DisplayFor's to display a Summary of the current values of my textboxes (what's been updated in the View, not what was passed in in the model).
In my Silverlight days, I'd simply have two-way binding between my 'Step1.FirstName' TextBox and a ViewModel property. In my Summary, I could simply display a TextBlock that was also bound to my ViewModel property, or I could use Element Binding to bind my TextBlock.Text proeprty to my Step1.FirstName.Text property.
I know I can't do that in MVC3, but I'm not sure how to solve this. I thought about just ajax posting the updated module and returning a new partial view called ModuleSummary, or something similar, but that seemed kinda hacky (and not entirely sure if that would mess up my file upload on the page).
Is there something I'm missing?
[Edit - sample code]
Scenario:
I'm editing a model which originally has a title of "My Module". Obviously on initial load, my DisplayFor model.title is going to be set to "My Module". Let's assume, on step 1, I change the title to "My New Module Title". What I'd like to know is if there's a way to "refresh" my model when I click the button to display Summary to display my new title.
#model CEAcademy.AddEditModuleModel
#using (Html.BeginForm("AddModule", "Module", FormMethod.Post, new { enctype = "multipart/form-data" })) {
#Html.ValidationSummary(false)
<fieldset>
<legend></legend>
<div id="step1">
<div class="editor-label">
#Html.LabelFor(model => model.title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.title)
#Html.ValidationMessageFor(model => model.title)
</div>
</div>
<div id="summary">
<div class="display-label">
#Html.LabelFor(model => model.title)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.title)
</div>
</div>
<input type="button" id="showSummary" value="Step 2: View Summary" />
</fieldset>
}
Someone just asked a similar question
Display form data before final submission (confirmation view)
I'll ask you the same thing I asked that person. Do you need to go to the server? Is there some extra validation you need to do before displaying the summary?
If not, then you can "easily" do this client side. Use javascript (jQuery or some other lib) to display the summary and at the end then POST the data.

Resources