Checking to see if Html Input textfield has value - asp.net-mvc

On my asp.net web app (mvc), I am wanting to check if the user entered a value in the text field when the button is clicked, and if it is to redirect to the next page. If not, to throw an exception. I looked up on how to do so, and attempted to use it with Html.BeginForm() but for some reason it still does enter my condition statement when I leave the textbox blank and hit the submit button.
ORIGINAL CODE:
SecondController:
[HttpPost]
public IActionResult Insert(String inputF)
{
if (inputF == null)
{
throw new Exception("You did not type anything in the textfield!!!!");
}
else
{
return RedirectToAction("FinalIndex", "Final");
}
}
I wanted it to throw an exception but not stop the program for proceeding like it return a message to the user in the UI but still record the exception that was made.
UPDATED CODE:
My SecondController:
[HttpPost]
public IActionResult Insert(String inputF)
{
if (!ModelState.IsValid || String.IsNullOrWhiteSpace(inputF.Input))
{
return View(inputF);
}
else
{
return RedirectToAction("FinalIndex", "Final");
}
}
It does not let me do String.IsNullOrWhiteSpace(inputF.Input) because it shows the following:
So I then removed the .Input from inputF.Input and it still gave me the the unhandled message in the picture below
My View:
#using CustomerSimulatorApp.Models
#model TextInput
<h2>Second page</h2>
#using (Html.BeginForm("Insert", "Second", FormMethod.Post))
{
#Html.TextBoxFor(r => r.Input);
<input id="Button" type="submit" value="button" />
}
My model:
namespace CustomerSimulatorApp.Models
{
public class TextInput
{
[Required, MinLength(1)]
public String Input { get; set; }
}
}
When I leave the text box empty & hit the button it returns this shown below:
Not sure, if that is what is exactly supposed to happen or if an actual exception was supposed to be thrown. Also, when I just type a single character in the box and hit the button it still allows me to proceed to the redirect and does not throw an exception regardless of my [Required MinLength(2)] on my attribute.
So my objective is to redirect the user to another page (FinalIndex) if the user typed something into the textbox and hits the button. If the user did not type anything in the text box and still hits the button to proceed to the next page, then it needs to throw an exception.
Am I doing something incorrectly? Any suggestions would be greatly appreciated it!

We got this resolved over chat, just had a few naming conventions we changed:
public IActionResult SecIndex(TextInput form)
Was the ultimate fix, instead returning a non-existing view.

You are almost there, but few changes are needed in view and controller side to get it working.
you need to have input button with type submit
#using (Html.BeginForm("Insert", "Second", FormMethod.Post))
{
#Html.TextBoxFor(r => r.Input);
<input id="Button" type="submit" value="button" />
}
and in controller action code should be like:
// this if checks if input textbox value is not present load back page with error
if (!ModelState.IsValid || String.IsNullOrWhiteSpace(inputF.Input))
{
return View(inputF);
}
else
{
// there was value in input redirect to Final controller action
return RedirectToAction("FinalIndex","Final");
}

Related

How to return to same url after submit button clicked from different ActionResult method in same controller using MVC5?

I want url to be remain same what it was before after submit is clicked, I don't want to display ActionResult method name
Before executing below code, my url was http://localhost/ProjectName/
[HttpPost]
public ActionResult ControllerSignIn(Models.SignIn signin)
{
ViewBag.name = "John";
return View("~/Views/Home/Index.cshtml");
}
After executing the above code, my URL become http://localhost/ProjectName/ControllerSignIn/
I tried below code also
[HttpPost]
public ActionResult ControllerSignIn(Models.SignIn signin,string returnUrl)
{
ViewBag.name = "John";
return View(returnUrl);
}
my partial view code
#using (Html.BeginForm("ControllerSignIn", "Home"))
{
//.... some text box
#Html.Hidden("returnUrl", this.Request.RawUrl)
<input type="submit" class="btn btn-sm btn-primary btn-rounded" value="Login" id="btnLoginSubmit" />
}
Note
My point is, wherever user logged in, after they logged in, it has to visit the same url
You need to realize that URL determines which controller and action should be executed. What you pass to a View() is not a URL, but a path. This path determines which view should be displayed...
// no matter what you put in "SomePath", your URL will remain the same.
return View("SomePath");
If you want to change the URL to http://localhost/ProjectName/ you need to redirect to that Controller's action:
[HttpPost]
public ActionResult ControllerSignIn(Models.SignIn signin)
{
ViewBag.name = "John";
/* return View("~/Views/Home/Index.cshtml"); <-- this has no effect on URL */
return RedirectToAction("MyController", "MyAction"); // this would take you to a different URL
}
If you want to redirect to: http://localhost/ProjectName/ (I assume ProjectName is your Controller and you want to redirect to the default action)... you need to return:
return RedirectToAction("ProjectName"); // redirect to default action of ProjectName controller

MVC [Required] attribute not working

I'm new to MVC and trying to do a simple application form with a check box to accept the terms.
I cant understand why my error message isnt showing.
This is my .cshtml
<div class="form-row">
<div class="validation-container">#Html.ValidationMessageFor(m => m.HasAcceptedTerms)
</div>
<div class="label-container">#Html.LabelFor(m => m.HasAcceptedTerms)</div>
<div class="form-control">#Html.EditorFor(m => m.HasAcceptedTerms)</div>
</div>
my ViewModel
[Required(ErrorMessage = "Please indicate you have read the statements above before sending your request")]
[Display (Name = "Please tick to show you accept all the above statements")]
public bool HasAcceptedTerms
{
get; set;
}
Controller
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult AppForm(AppFormViewModel App)
{
if (ModelState.IsValid)
{
return View();
}
return View(App);
}
When I click the button, the page refreshes with no changes. While debugging, the Model.State is false, so I really cant understand why nothing is happening. Does anyone have any ideas?
Being a value type, your bool has a default value of false - this is a value and therefore does not get recognised as "missing". You will need to validate that the value is true, rather than being required.
You could look at this question for a way to achieve this.

How to return a single string to a div in my current page from HTTP POST in ASP.NET MVC 5?

I'm trying to post a message after a contact form, indicating to the user that their message has been sent after they click the submit button. I don't want to redirect to a different page or to return a different view inside my HTTP Post action method. How do I do something like that in ASP.NET MVC framework?
Below is my code sample:
#*contactus.cshtml*#
#model MySite.Models.ContactModel
#using (Html.BeginForm())
{
<div class="col-md-6">
<div class="form-group">
#Html.TextBoxFor(model => model.Name})
<p>#Html.ValidationMessageFor(model => model.Name)</p>
</div>
<div class="form-group">
#Html.TextBoxFor(model => model.Email)
<p>#Html.ValidationMessageFor(model => model.Email)</p>
</div>
<div class="form-group">
#Html.TextAreaFor(model => model.Message)
<p>#Html.ValidationMessageFor(model => model.Message)</p>
</div>
<div class="col-lg-12">
<button type="submit">Send Message</button>
</div>
</div>
}
#*ContactModel.cs*#
public class ContactModel
{
[Required(ErrorMessage = "* Please enter your name.")]
[StringLength(100, MinimumLength=3, ErrorMessage="* Please enter your full name.")]
public string Name { get; set; }
[Required]
[EmailAddress(ErrorMessage="* Not a valid email address.")]
public string Email { get; set; }
[Required]
public string Message { get; set; }
}
I only have a contact us form right now on my home/index page, and I don't want to redirect it to any other pages. I would like to display a message right below the Send Message button, but I'm not sure how to go about it using the action method below:
#*HomeController.cs*#
public ActionResult Index(ContactModel model)
{
if (ModelState.IsValid)
{
// this is my helper library, for brevity, I'm not copying it.
EmailHelper emailService = new EmailHelper();
bool success = emailService.SendEmail(model.Name, model.Email, model.Message);
return Content(success ? "success" : "no...something went wrong :(");
} else {
return View(model);
}
}
Right now this controller will return the string inside Content which replaces my entire page, and I would like the string to be returned below my contact form. Also, I have two sections on the same html page with Contact Form as the second one, when I return View(model), it automatically redirects to the first section, which isn't ideal... How do I tell the controller to only redirect it to the second section after the POST method? In addition, I feel like it would be more efficient if it didn't return the whole page... so is there a way to only return a Message string to the div?
You can place a hidden div on the page which will contain the message.
Then when your form has been submitted, capture the click event for your button, and use that to display the hidden message.
Let me know if you need a code example. Posting your form would help us answer you more specifically.
To only show the success message if the form is successfully sent, I would recommend setting a value in the ViewBag in the POST action of the controller and then returning that same page if you want to still have the same page showing. On the View itself, you could then place an If statement to test if the ViewBag variable contains a value and if so, display the message.
Controller:
[HttpPost]
public ActionResult YourAction(YourModel m)
{
//Do stuff to send the contact form
...
if(error)
{
ViewBag.Message = "There was a problem sending the form.";
}
else
{
ViewBag.Message = "The form was sent successfully!";
}
return View(m);
}
View:
#if(ViewBag.Message != null)
{
<div>#ViewBag.Message</div>
}
This lets you check if the form was posted successfully on the server before telling the user the result and will only display a message if ViewBag.Message has been set. Note that you can have as many ViewBag variables as you want and can name them whatever you want... just remember which one you use in which place.
EDIT:
Following the comments, this could also be done using an AJAX call. I'll use the jQuery .post() method for simplicity sake.
In Script:
<script>
$(document).on('click', "#buttonId", function() {
var nameText = $("#IdOfNameField").val();
var emailText = $("#IdOfEmailField").val();
var messageText = $("#IdOfMessageField").val();
$.post('#Url.Content("~/Controller/AJAXPostContactForm")',//the url to post to
{name: nameText, email: emailText, message: messageText }, //these are values to be sent to the action
function(){ //this is the success function
$("#successMessage").val("Form posted successfully.");
}
)
.fail(function() {//failure function
alert("Something went wrong.");
});
}
</script>
Controller:
public void AJAXPostContactForm(string name, string email, string message)
{
try
{
//do stuff with the information passed into the action
}
catch(exception e)
{
//Handle errors. If error thrown, Ajax should hit fail block in script
}
finally
{
//do any cleanup actions
}
}
View:
<div id="successMessage"></div>
I have not tested this code but it should theoretically work. On a specific button click, it will get the values from the form fields, post those values to a specialized ActionResult in the controller, and then return a message about what happened.

Calling Function upon field change in MVC

I have a entity called WorkOrder which gets assigned to an Employee.
I want send an email notification when the workorder has been asigned. This can happen on my MVC Create or Edit Action (POST).
The problem i have is i have to do checks to see if the value has changed in the Edit to determine if i should send an email.
Is there a better place to call the SendEmail Function, like in the Entity Model itself?
If you are talking about posting from a view, you could create and bind the existing value to a hidden field in your form when loading the view. Then, on the POST to your action you can check to see if the value from the field is different from the one that is on the hidden field.
Example of View:
#using (Html.BeginForm("MyAction", "MyController")
{
#Html.HiddenFor(m => m.CurrentValue)
#Html.TextBoxFor(m => m.Value)
<input type="submit" value="submit" />
}
Example of Action GET
public ActionResult MyAction()
{
var viewModel = GetModelFromSomeWhere();
viewModel.CurrentValue = viewModel.Value;
return this.View(viewModel);
}
Example of Action POST
[HttpPost]
public ActionResult MyAction(ViewModel model)
{
if (model.Value != model.CurrentValue)
{
// It has changed! Send that email!
}
}

ASP.NET MVC, passing Model from View to Controller

I'm having trouble with ASP.NET MVC and passing data from View to Controller. I have a model like this:
public class InputModel {
public List<Process> axProc { get; set; }
public string ToJson() {
return new JavaScriptSerializer().Serialize(this);
}
}
public class Process {
public string name { get; set; }
public string value { get; set; }
}
I create this InputModel in my Controller and pass it to the View:
public ActionResult Input() {
if (Session["InputModel"] == null)
Session["InputModel"] = loadInputModel();
return View(Session["InputModel"]);
}
In my Input.cshtml file I then have some code to generate the input form:
#model PROJ.Models.InputModel
#using(Html.BeginForm()) {
foreach(PROJ.Models.Process p in Model.axProc){
<input type="text" />
#* #Html.TextBoxFor(?? => p.value) *#
}
<input type="submit" value="SEND" />
}
Now when I click on the submit button, I want to work with the data that was put into the textfields.
QUESTION 1: I have seen this #Html.TextBoxFor(), but I don't really get this "stuff => otherstuff". I concluded that the "otherstuff" should be the field where I want to have my data written to, in this case it would probably be "p.value". But what is the "stuff" thing in front of the arrow?
Back in the Controller I then have a function for the POST with some debug:
[HttpPost]
public ActionResult Input(InputModel m) {
DEBUG(m.ToJson());
DEBUG("COUNT: " + m.axProc.Count);
return View(m);
}
Here the Debug only shows something like:
{"axProc":[]}
COUNT: 0
So the returned Model I get is empty.
QUESTION 2: Am I doing something fundamentally wrong with this #using(Html.BeginForm())? Is this not the correct choice here? If so, how do I get my model filled with data back to the controller?
(I cannot use "#model List< Process >" here (because the example above is abbreviated, in the actual code there would be more stuff).)
I hope someone can fill me in with some of the details I'm overlooking.
Change your view to some thing like this to properly bind the list on form submission.
#using(Html.BeginForm()) {
for(int i=0;i<Model.axProc.Count;i++){
<span>
#Html.TextBoxFor(model => model.axProc[i].value)
</span>
}
<input type="submit" value="SEND" />
}
In #Html.TextBoxFor(stuff => otherstuff) stuff is your View's model, otherstuff is your model's public member.
Since in the View you want to render input elements for the model member of a collection type (List), you should first create a separate partial view for rendering a single item of that collection (Process). It would look something like this (name it Process.cshtml, for example, and place into the /Views/Shared folder):
#model List<PROJ.Models.Process>
#Html.TextBoxFor(model => p.value)
Then, your main View would look like this:
#model PROJ.Models.InputModel
#using(Html.BeginForm()) {
foreach(PROJ.Models.Process p in Model.axProc){
#Html.Partial("Process", p)
}
<input type="submit" value="SEND" />
}
Also, check that the loadInputModel() method actually returns something, e.g. not an empty list.

Resources