I have a scenario where i want one value "tab" to be taken from one action to its view and then from view to another action. I have put the tab value in viewdata to be accessed in view.
Please suggest how do i access this "tab" value in view and then forward it to the action "Authenticate".
I am working on mvc3 2010. Below is my code:
public ActionResult Index(string tab)
{
try
{
ViewData["tab"] = tab;
return View("Authorize");
}
catch (Exception ex)
{
return View("EmptySearch");
}
}
#using (Html.BeginForm("Authenticate", "Authorization"))
{
<div>
<fieldset>
<legend>User Information</legend>
<div class="editor-label">
#Html.Label("Password")
#Html.TextBox("password")
#Html.ValidationMessageFor(m => m.password)
</div>
<p>
<input type="submit" value="Submit" />
</p>
</fieldset>
</div>
}
[AcceptVerbs("POST")]
public ActionResult Authenticate(FormCollection collection)
{
try
{
string password = collection["password"];
password = password.Trim();
//ViewData["BatchNumber"] = password;
//dynamicsContext.CommandTimeout = 180;
//List<BatchMember> batchMemberList =
// Queries.compiledBatchQuery(dynamicsContext, password).ToList<BatchMember>();
return RedirectToAction("Index", "GreatPlains");
}
catch (Exception ex)
{
return View("EmptySearch");
}
}
Keep it in a Hidden field in your Form and it will be available in your Post action method
#using (Html.BeginForm("Authenticate", "Authorization"))
{
<div>
<fieldset>
<legend>User Information</legend>
<div class="editor-label">
#Html.Label("Password")
#Html.TextBox("password")
#Html.ValidationMessageFor(m => m.password)
</div>
<p>
#Html.Hidden("Tab", ViewData["tab"])
<input type="submit" value="Submit" />
</p>
</fieldset>
</div>
}
And in your HttpPOST Action method
[HttpPost]
public ActionResult Authenticate(FormCollection collection)
{
var tabValue=collection["Tab"]
//remaining code
}
You can use TempData, Session or cookie, or you can add the value of tab as a hidden field in your form and keep using ViewData.
Related
I apologize if the heading is not very clear.
So, what I want to do is following.
I have a model class called "Class" that contains a list of "Students". I have a view that shows a checklist of Students. From that checklist I want to pass the selected students back to controller, where I will update the Database and my class will have new students and the added students will have a new class.
Here is what I have done so far but now I am stuck. Thanks in advance.
These are my controller actions
[HttpGet]
public ActionResult AddStudents(int? id)
{
List<Student> students = (from std in db.Students
where std.St_cl_fk_id == null select std).ToList();
//ViewBag.students = students;
return View("Add_Students",students);
}
[HttpPost, ActionName("AddStudents")]
public ActionResult AddStudentsPost(int? id,List<Student> students)
{
if(ModelState.IsValid)
{
var temp = id;
Class #class = db.Classes.Find(id);
foreach (var item in students)
{
if (Request.Form[item.St_id.ToString()] != null)
{
#class.Students.Add(item);
}
}
db.Entry(#class).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index", "Classes");
}
return View("Add_Student");
}
Here is my view
#model IEnumerable<GMASchoolProject.Models.Student>
#{
ViewBag.Title = "Add_Students";
}
<h4>Student List</h4>
#using (Html.BeginForm())
{
<div class="row">
<div class="col-lg-8 col-lg-offset-2">
<div class="panel panel-default">
<div class="panel-heading">
Check Students
</div>
<div class="form-group">
<div class="col-md-10">
<table>
#foreach (var std in Model)
{
<tr>
<td><input type="checkbox" name="#std.St_id" value="#std.IsSelected" /></td>
<td>#Html.Label((string)std.St_name)</td>
</tr>
}
</table>
</div>
</div>
<div class="form-group" style="margin:15px,0,15px,0;">
<div class="col-md-offset-5 col-md-2">
<input type="submit" value="Add Students" class="btn btn-primary" />
</div>
</div>
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index", null, new { #class = "btn btn-danger" })
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Please let me know if there is anything else that I am doing wrong, I am a newbie in this area. THanks
First, instead of binding the view to a list of students, bind the model to your Class object that has a list of students in it. That way, when you submit (post), you are sending the whole Model object into the Controller.
Change your AddStudentsPost method to take in Class object and do your logic there.
Finally, change the name of the "Class" object to something else, such as, "Course". Class should be reserved for actual classes so not to cause confusion.
You aren't far off, so keep going
Validate Input is not working.The form gets submitted and the success view is displayed even when the form is posted with html tags
<b> hello </b>
Why is the cross site scripting prevention not working? It should be enabled by default right?
Razor View
<h4 style="color:purple">
<b>ID:</b> #ViewBag.ID <br />
<b>Name:</b> #ViewBag.Name <br />
</h4>
<hr />
#using (Html.BeginForm("register", "Adder", FormMethod.Post))
{
<div class="form-group">
#Html.TextArea("comments");
<input type="submit" />
</div>
}
Controller Method
[HttpPost]
public string register(string val)
{
// quickdbEntities1 ent = new quickdbEntities1();
// Player p1 = ent.Players.FirstOrDefault(p => p.Name == "name");
//// ent.Players.Add(player);
//// int res = ent.SaveChanges();
// ViewBag.id = player.PlayerId;
// ViewBag.Name = p1.Name;
return ("success");
}
Update:
I have added DataAnnotation [Required] and now uses a form like this.Still the form submits
#model Vidly.Domain.Player
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#section scripts
{
#Scripts.Render("~/bundles/jqueryval" )
}
#using (Html.BeginForm("register", "Adder", FormMethod.Post))
{
<div class="form-group">
#Html.TextBoxFor(m => m.Name,new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Name)
<input type="submit" name="submit" />
</div>
}
It is because you are accepting the parameter as string and no validation script in view page (as of we can't see if the layout page has the scripts).
Goal:
If you retrieve a error based on the input, it should be displayed in ValidationSummary in relation to ajax without the webpage being refreshed.
Problem:
I have tried to make it but it doesn't work so well.
What part am I missing?
Thank you!
Info:
*I have found some webpages but they do not fit exactly to my purpose.
*I'm using ASP.net mvc
#model WebApplication1.Controllers.PersonnelModel
#{
ViewBag.Title = "Ajax";
}
<h2>Ajax</h2>
<h2>AjaxViewModel</h2>
#using (Html.BeginForm("HtmlViewModel", "Home", null))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>PersonnelModel</legend>
<div class="editor-label">
#Html.LabelFor(model => model.UserName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.UserName)
#Html.ValidationMessageFor(model => model.UserName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.MailAdress)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.MailAdress)
#Html.ValidationMessageFor(model => model.MailAdress)
</div>
</fieldset>
<p>
<input type="submit" value="Html Form Action" />
</p>
}
<br/>
<br />
<h2>AjaxViewModel</h2>
#using (Ajax.BeginForm("AjaxViewModel", "Home", new AjaxOptions { UpdateTargetId = "result" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>PersonnelModel</legend>
<div id="result"></div>
<div class="editor-label">
#Html.LabelFor(model => model.UserName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.UserName)
#Html.ValidationMessageFor(model => model.UserName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.MailAdress)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.MailAdress)
#Html.ValidationMessageFor(model => model.MailAdress)
</div>
</fieldset>
<p>
<input type="submit" value="Ajax Form Action" />
</p>
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery-ajax-unobtrusive#3.2.4/jquery.unobtrusive-ajax.min.js"></script>
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
namespace WebApplication1.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult HtmlViewModel(PersonnelModel Pmodel)
{
return Content("Hi " + Pmodel.UserName + ", Thanks for the details, a mail will be sent to " + Pmodel.MailAdress + " with all the login details.", "text/html");
}
[HttpPost]
public ActionResult AjaxViewModel(PersonnelModel Pmodel)
{
/*
ModelState.AddModelError("", "login is fail");
return View("Index", Pmodel);
*/
return Content("Hi " + Pmodel.UserName + ", Thanks for the details, a mail will be sent to " + Pmodel.MailAdress + " with all the login details.", "text/html");
}
}
public class PersonnelModel
{
[Required(ErrorMessage = "UserName Required.")]
public string UserName { get; set; }
[Required(ErrorMessage = "Email id Required.")]
public string MailAdress { get; set; }
}
}
EDIT - 03/11/2017 : There is an easy way to do this
Create a partial view for the form, Let's call it Form.cshtml and move the markup needed for the form to that. For your ajax form, set the data-ajax-mode attribute value to replace and data-ajax-update value to the id of the same form.
If you are using Ajax.BeginForm helper method, this is how you will do
#model PersonnelModel
#using (Ajax.BeginForm("Create", "Home",
new AjaxOptions { UpdateTargetId = "myform",
InsertionMode = InsertionMode.Replace },new { id="myform"}))
{
#Html.ValidationSummary("", true)
#Html.TextBoxFor(f => f.UserName)
#Html.ValidationMessageFor(model => model.UserName)
#Html.TextBoxFor(f => f.MailAdress)
#Html.ValidationMessageFor(model => model.MailAdress)
<input type="Submit" id="submit" value="Submit" class="btn btn-default" />
}
Now in your main view, simple call this partial view
#model PersonnelModel
<h2>My form below</h2>
#Html.Partial("Form",Model)
Now in the action method, when model state validation fails, return the partial view.
public ActionResult Create(PersonnelModel model)
{
if (ModelState.IsValid)
{
// to do : Save
}
if (Request.IsAjaxRequest())
{
return PartialView("Form",model);
}
return View(model);
}
Now when you submit the form and model state validation fails, the action method code will return the partial view result with the validation error messages (generated by the validation helpers) and the jquery.unobtrusive-ajax.js library code will replace (because we specified that with data-ajax-mode="replace") the content of the result of the jquery selector #data-ajax-update (the form tag and it's inner contents) with the response coming back from the server.
This should do it. Less client side code, compared to my old approach (below)
The Html.ValidationSummary method will be executed when the razor view gets executed. If you are doing a normal form post (non ajax), your action method usually returns to the same view when Model validation fails (assuming you write code like that) and the razor view code gets executed and the ValidationSummary method will read the validation errors from the model state dictionary and render the error messages.
When you use Ajax.BeginForm helper method the helper will generate some extra data attributes on the form and as long as you have included the jquery.unobtrusive-ajax.min.js script file, the form submit will be hijacked and it will do an ajax form submit instead.
When you do the ajax form submit, if you want to render model validation messages, you need to explicitly read the model validation errors and return that as a JSON response which your client side code can read and display in the UI.
[HttpPost]
public ActionResult Index(PersonnelModel model)
{
if (ModelState.IsValid)
{
return Json(new {status = "success", message= "Thanks for the details"});
}
else
{
var errors = new List<string>();
foreach (var modelStateVal in ViewData.ModelState.Values)
{
errors.AddRange(modelStateVal.Errors.Select(error => error.ErrorMessage));
}
return Json(new {status = "validationerror", errors = errors});
}
}
Now in your view, make sure you have a success handler for your ajax begin form to handle the response json
#using (Ajax.BeginForm("Index", "Home", new AjaxOptions { OnSuccess = "OnSuccess", }))
{
#Html.ValidationSummary("", true)
#Html.TextBoxFor(model => model.MailAdress)
<!--Your other form input elements-->
<input type="submit" value="Html Form Action" />
}
Note that i used #Html.ValidationSummary method with 2 overloads and passing an empty string as the first param. This will always render a ul element within the div which has class validation-summary-valid.
Now create your OnSuccess function and check the response and see whether response has a status property and the value of it is validationerror. If yes, loop through the errors collection and add a new li element with the error.
function OnSuccess(response) {
var $summaryUl = $(".validation-summary-valid").find("ul");
$summaryUl.empty();
if (response.status === 'validationerror') {
$.each(response.errors,
function(a, b) {
$summaryUl.append($("<li>").text(b));
});
} else {
alert(response.message);
}
}
I am new to asp.net MVC 4. i have some problems dealing with attributs
i use [httppost] attribut in my controller but it's not working
it's not even invoked
my controller
public ActionResult Inscription()
{
return View();
}
[HttpPost]
public ActionResult Inscription(Candidat candidat)
{
if (!ModelState.IsValid)
{
return View(candidat);
}
return RedirectToAction("Index");
}
my view
#model ProcRec.Models.Candidat
#{
ViewBag.Title = "Inscription";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#Html.ValidationSummary(true)
<div class="form_settings">
#using (Html.BeginForm("Inscription", "CandidatController"))
{
<table ="#FFFFFF">
<tr>
<td>#*<span >Nom :</span>*# #Html.LabelFor(model => model.nom_candidat)</td>
<td> #Html.TextBoxFor(model => model.nom_candidat)
#Html.ValidationMessageFor(Model => Model.nom_candidat)
.
.
</table>
}
<input type="submit" class="submit right" value="Inscription" />
think you for your help
Just correct beginform as :
#using (Html.BeginForm("Inscription", "CandidatController",FormMethod.Post))
{
........
<input type="submit" class="submit right" value="Inscription" />
}
Put submit button inside BeginForm() and give BeginForm() FormMethod as Post.
Thankzz..
Put your <submit> element inside the form:
#using (Html.BeginForm())
{
...
<input type="submit" class="submit right" value="Inscription" />
}
Don't need to change Html.BeginForm. By default it's POST.
Check : FormExtensions.BeginForm
Only issue is with the submit button, it should be inside form as mentioned in Andy Refuerzo's answer. Don't know why it is down-voted.
i'm trying to upload a file with ASP MVC4, i give you my situation:
I have a model class "Movie" with some atributes (doesn't matter)
I want to add some code to my controller and View part without touching the model, because we want to make the image difrent to the model.
So, here's an example of my view code, i'll bold the lines added by me:
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Movie</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Duration)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Duration)
#Html.ValidationMessageFor(model => model.Duration)
</div>
//ADDED BY ME:
<div class="editor-label">
<p>Select a file</p>
</div>
<div class="editor-field">
<input type="file" name="fileUpload" />
</div>//END OF MY CODE
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
So you can see that i have some code generated by ASP which allows me to add a new user to the db, and a "input" added by me to upload the image.
The problem is that when i try to recover that image from the controller, the "Request.Files" atributte is empty, so i can't recover any image, and of course i can't upload it, here's my controller code:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Movie movie)
{
if (ModelState.IsValid)
{
db.MovieContext.Add(movie);
db.SaveChanges();
foreach (string file in Request.Files)
{
var postedFile = Request.Files[file];
postedFile.SaveAs(Server.MapPath("~/UploadedFiles") + pelicula.Id);
}
return RedirectToAction("Index");
}
return View(movie);
}
Don't know why the "Request.Files" is empty, so if anyone can help me it would be great, Thank you so much
Try the below:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Movie movie, HttpPostedFile fileUpload)
{
if (ModelState.IsValid)
{
db.MovieContext.Add(movie);
db.SaveChanges();
var postedFile = fileUpload;
postedFile.SaveAs(Server.MapPath("~/UploadedFiles") + pelicula.Id);
return RedirectToAction("Index");
}
return View(movie);
}
Lets see if we can find out whats wrong. Try the following and show us the errors:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Movie movie, HttpPostedFile fileUpload)
{
if (ModelState.IsValid)
{
db.MovieContext.Add(movie);
db.SaveChanges();
var postedFile = fileUpload;
postedFile.SaveAs(Server.MapPath("~/UploadedFiles") + pelicula.Id);
return RedirectToAction("Index");
}
var content = "";
foreach (ModelState modelState in ViewData.ModelState.Values)
{
foreach (ModelError error in modelState.Errors)
{
content += error.ErrorMessage + ", " + error.Exception + "<br/>";
}
}
return Content(content);
//return View(movie);
}
Antevirus has the answer but I hat to dig into comments to find it out. In short the problem for was that I didnt specify any encodings for my form which is
enctype = "multipart/form-data"
Here is the full code:
#using (Html.BeginForm("Create", "Members", FormMethod.Post, new { #id = "member-form", #enctype = "multipart/form-data" }))
{
<div class="form-group">
<label class="control-label col-md-2">Picture</label>
<div class="col-md-10">
<input id="fileUpload" type="file" name="fileUpload" class="file-loading">
</div>
</div>
}
I am using file-input for bootstrap