Query string param is missed when form validation fail - c#

I have an form with following url:
CreateEntity?officeCodeId=5
When I send form to validate and if validation is fail it returns just CreateEntity url. No officeCodeId=5.
if user click enter on URL or F5 - my site fail - it require missing officecodeId param. I can save it to the session or in the other storage. But I want to have it in the URL
My view:
[HttpGet]
public virtual ActionResult CreateEntity(int? officeCodeId)
{
var model = new CreateViewModel();
FillViewModel(model, officeCodeId);
return View("Create", model);
}
[HttpPost]
protected virtual ActionResult CreateEntity(TEditViewModel model)
{
if (ModelState.IsValid)
{
//Do some model stuff if
}
return View("Create", model);
}
EDIT.
My View:
using (Html.BeginForm("CreateEntity", "Employee", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.HiddenFor(x => x.OfficeCodeId)
<div>
#Html.LabelFor(model => model.FirstName, CommonRes.FirstNameCol)
#Html.TextBoxFor(model => model.FirstName, Model.FirstName)
#Html.ValidationMessageFor(model => model.FirstName)
</div>
<div>
#Html.LabelFor(model => model.LastName, CommonRes.LastNameCol)
#Html.TextBoxFor(model => model.LastName, Model.LastName)
#Html.ValidationMessageFor(model => model.LastName)
</div>
<div> <div class="input-file-area"></div>
<input id="Agreements" type="file" name="Agreements"/>
</div>
}
Edit 2.
Adding:
#using (Html.BeginForm("CreateEntity", "Employee", FormMethod.Post, new { officeCodeId = Model.OfficeCodeId, enctype = "multipart/form-data" }))
Haven`t help.
It produce the following form:
<form action="/PhoneEmployee/CreateEntity" enctype="multipart/form-data" method="post" officecodeid="5">
Solution Is
<form action="#Url.Action("CreateEntity", "Employee")?officecodeid=#Model.OfficeCodeId" enctype="multipart/form-data" method="post">

The problem is your HttpPost action doesn't have any notion of an id parameter. If you want to support a similar URL then make the action signature support that parameter e.g.
[HttpGet]
public ActionResult CreateEntity(int? officeCodeId)
[HttpPost]
public ActionResult CreateEntity(int officeCodeId, EditViewModel model);

Your actions should looks like this:
Actions:
[HttpGet]
public virtual ActionResult CreateEntity(int? officeCodeId)
{
var model = new CreateViewModel();
FillViewModel(model, officeCodeId);
return View("Create", model);
}
[HttpPost]
public virtual ActionResult CreateEntity(ViewModel model)
{
if (model.IsValid) {
// save...
return RedirectToAction("EditEntity", newId!!!);
}
return View("Create", model);
}
Html:
#using (Html.BeginForm()) {
#Html.HiddenFieldFor(m => Model.officeCodeId)
...
}
Your officeId should be in model. And on html form you can store it in hidden field.

Your final answer is excellent and works great, although you can further enhance it to make it more generic by simply including Request.QueryString:
<form action="#Url.Action("CreateEntity", "Employee")?#(Request.QueryString)"
enctype="multipart/form-data" method="POST">
Then use the POST action:
[HttpPost]
protected virtual ActionResult CreateEntity(TEditViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}

Related

Html Helpers in View are empty after Post

HTML Helpers are empty after model with values are passed in View
Textbox values are empty after returning model to view.
#model GSG.Tools.Models.EmailTemplateViewModel
#using (Html.BeginForm("EmailTemplate", "Admin", FormMethod.Post))
{
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<table class="table" style="width:100%;">
<tr>
<td>
#Html.LabelFor(m => m.From)
<span style="color:red;">*</span>
</td>
<td>
#Html.TextBoxFor(m => m.From, new { #class = "form-control", #id = "txtFrom" })
#Html.ValidationMessageFor(m => m.From, "", new { #class = "text-danger" })
</td>
<td>#Html.LabelFor(m => m.To)</td>
<td>
#Html.TextBoxFor(m => m.To, new { #class = "form-control", #id = "txtTo" })
</td>
</tr>
</table>
[HttpPost]
public IActionResult EmailTemplate(EmailTemplateViewModel model)
{
if (!ModelState.IsValid)
{
**My Code
return View(model);
}
please clarify with your question as It is not clear as whether the textbox is empty after the form submission or before the form submission. Your method is designated as the post method so it should be for submitting the form. There should be another method to display the view.
For an example, This is the method to display the view for edit/display.
[HttpGet]
public IActionResult EmailTemplate()
{
EmailTemplateViewModel model = new EmailTemplateViewModel();
**Your Code to fetch the data from the database.
return View(model);
}
Now please note, Whenever you submit the form and if any validation error may happen then, it wont return anything in your case just because, you have returned the view inside the if condition. If you want to display the data even if the validation fires then please return the view outside the if condition.
For an example,
[HttpPost]
public IActionResult EmailTemplate(EmailTemplateViewModel model)
{
if (!ModelState.IsValid)
{
**My Code
}
return View(model);
}
the [HttpPost] method is for submitting the form. When you open the url you will have a [HttpGet] method
[HttpGet]
public IActionResult EmailTemplate()
{
EmailTemplateViewModel model = new EmailTemplateViewModel();
//Load Data here
return View(model);
}
The other case maybe, is it that you are trying to submit a form and fill the data in the post request?
Then your condition is being invalidated.
[HttpPost]
public IActionResult EmailTemplate(EmailTemplateViewModel model)
{
if (!ModelState.IsValid)
{
**My Code
return View(model);
}
else
{
//populate data here too.
return View(model);
}
}

MVC Action not firing

Controller :
public ActionResult Insert()
{
return View();
}
public ActionResult Insert(Employee emp)
{
Employee emp1 = new Employee();
emp1.insert(emp);
return View();
}
cshtml
#using (Html.BeginForm("Employee", "Insert", FormMethod.Post))
{
#Html.TextBoxFor(model => model.name)
#Html.TextBoxFor(model => model.Email)
#Html.TextBoxFor(model => model.mob)
<input type="button" value="Register me" />
}
I have to save my model values on button click ('Register me'). Thanks in advance.
Try to set attributes in your controller:
[HttpGet] // here ([HttpGet] is default so here you can delete this attribute)
public ActionResult Insert()
{
return View();
}
[HttpPost] // here
public ActionResult Insert(Employee emp)
{
Employee emp1 = new Employee();
emp1.insert(emp);
return View();
}
To call some action you need to submit your form. Change your button to submit type:
<input type="submit" value="Register me" /> // type="button" -> type="submit"
Also, in BeginForm you should firstly specify action name and then controller name:
#using (Html.BeginForm("Insert", "Employee", FormMethod.Post))
Its Because you have not declared HTTP POST on INSERT action
[HttpPost]
public ActionResult Insert(Employee emp)
{
Employee emp1 = new Employee();
emp1.insert(emp);
return View();
}
When you are using Beginform and your FormMethod is Post the related Action needs to have same kind of HTTP, By the way it doesn't matter if you have [HttpGet] on first ActionResult Because in MVC, any ActionResult that haven't declared any type of HTTP request/respond are known as [HttpGet]
Also in your BeginForm():
#using (Html.BeginForm("ActionName(Insert)", "ControllerName", FormMethod.Post))
{
#Html.TextBoxFor(model => model.name)
#Html.TextBoxFor(model => model.Email)
#Html.TextBoxFor(model => model.mob)
<input type="submit" value="Register me" />
}

ASP.NET MVC - How to upload an image and save URL in the database

I would appreciate if anyone could help me with this. I have input file control in a form in a view and when someone picks a picture and clicks the submit button on the form, that file has to be saved in /Pictures folder in the application and file path needs to be saved in SQL database as string (like: /Pictures/filename).
Models class part:
[Table("Automobil")]
public partial class Automobil
{ .....
[Required]
[StringLength(30)]
public string Fotografija{ get; set; }
......
View (Create) file part:
#using (Html.BeginForm("Create", "Automobili", FormMethod.Post, new { enctype = "multipart/form-data" }))
....
<div class="form-group">
<div class="editor-field">
#Html.TextBoxFor(model => model.Fotografija, new { type = "file" })
#Html.ValidationMessageFor(model => model.Fotografija, "", new { #class = "text-danger" })
</div>
</div>
....
Controller part:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "AutomobilID,Marka,Model,Godiste,Zapremina_motora,Snaga,Gorivo,Karoserija,Fotografija,Opis,Cena,Kontakt")] Automobil automobil)
{
if (ModelState.IsValid)
{
db.Automobils.Add(automobil);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(automobil);
}
What do I need to do so the photo(Fotografija) could be saved in the application folder Pictures, and file path in SQL base (like /Pictures/filename)?
Thank you in advance for helping the beginner.
Looks like your Fotografija property is string type where you want to save the unique file name. You do not want to use that field to get the file from the browser. Let's use another input field for that.
#using (Html.BeginForm("Index", "Home", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
<div class="form-group">
<div class="editor-field">
#Html.TextBoxFor(model => model.Model)
#Html.ValidationMessageFor(model => model.Model)
</div>
</div>
<!-- TO DO : Add other form fields also -->
<div class="form-group">
<div class="editor-field">
<input type="file" name="productImg" />
</div>
</div>
<input type="submit" />
}
Now update your HttpPost action method to have one more parameter of type HttpPostedFileBase. The name of this parameter should be same as the input file field name we added (productImg)
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "AutomobilID,Marka,Model,Godiste,
Zapremina_motora,Snaga,Gorivo,Karoserija,Opis,Cena,Kontakt")] Automobil automobil,
HttpPostedFileBase productImg)
{
if (ModelState.IsValid)
{
if(productImg!=null)
{
var fileName = Path.GetFileName(productImg.FileName);
var directoryToSave = Server.MapPath(Url.Content("~/Pictures"));
var pathToSave = Path.Combine(directoryToSave, fileName);
productImg.SaveAs(pathToSave);
automobil.Fotografija= fileName;
}
db.Automobils.Add(automobil);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(automobil);
}
You have to remove any validation data annotation decoration(Ex : [Required], [MinLength] etc) on the Fotografija field.
I also strongly suggest you to update the fileName before saving to be a unique one to avoid collision/overwriting of existing files. You can add the DateTime current value to the file name (Before the extension) to make it unique
The code that I have in controller is the basic one:
// GET: Automobili/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Automobil automobil = db.Automobils.Find(id);
if (automobil == null)
{
return HttpNotFound();
}
return View(automobil);
}
// POST: Automobili/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "AutomobilID,Marka,Model,Godiste,Zapremina_motora,Snaga,Gorivo,Karoserija,Fotografija,Opis,Cena,Kontakt")] Automobil automobil)
{
if (ModelState.IsValid)
{
db.Entry(automobil).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(automobil);
}
How to change it to be compatible with the create code above?
Thank you.

Partial views and html forms Asp Mvc

I am attempting to render a partial view that contains a simple html form. I want to render the form from a controller as I handle the postback from an overloaded controller method. I have tried #Html.Action("ContactForm")but I get an Exception because child actions cannot redirect.
My Controller:
public ActionResult Index()
{
return View();
}
[HttpGet]
public ActionResult ContactForm()
{
return PartialView(new ContactForm());
}
[HttpPost]
public ActionResult ContactForm(ContactForm Contact)
{
return RedirectToAction("FormResults", new { ContactForm = Contact });
}
public ActionResult FormResults(ContactForm Contact)
{
return PartialView(Contact);
}
My Form:
#using(Html.BeginForm())
{
<h2>Contact Form</h2>
<div class="input-group">
<h4>#Html.LabelFor(m => m.FirstName, "First Name")</h4>
#Html.TextBoxFor(m => m.FirstName, new { #class = "form-control", #placeholder = "First Name" })
</div>
<div class="input-group">
<h4>#Html.LabelFor(m => m.LastName, "Last Name")</h4>
#Html.TextBoxFor(m => m.LastName, new { #class = "form-control", #placeholder = "Last Name" })
</div>
<div class="input-group">
<h4>#Html.LabelFor(m => m.Email, "Email")</h4>
#Html.TextBoxFor(m => m.Email, new { #class = "form-control", #placeholder = "Email", #type = "text" })
</div>
<input type="submit" class="btn btn-info" value="Submit" />
}
Any Help on how I would accomplish this would be appreciated.
try surrounding the form with a div and a certain id and use:
#using(Ajax.BeginForm("ContactForm","YourController",new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "yourCertainId",
HTTPMethod = "POST"
})
and your ActionMethod:
[HttpPost]
public ActionResult ContactForm(ContactForm Contact)
{
return Partial("YourPartialName", Contact });
}
make sure that you include the bundle jqueryval on the bottom of your view.
you wont need the second controller method "FormResults"
Does something like this not work for you?
I don't think you need a redirect.
[HttpPost]
public ActionResult ContactForm(ContactForm Contact)
{
return PartialView("FormResults", Contact);
}
This uses the
PartialView(string viewName, object model)
overload of the PartialView method in the Controller class.
This allows you to use a View that doesn't match the ActionResult's method name.
The same thing works for the plain "View" method as well.

How to get textbox value from view to controller in mvc4 on submit button click

How to get the textbox value from view to controller in mvc4?If I using httppost method in controller the page cannot found error was came.
View
#model MVC_2.Models.FormModel
#{
ViewBag.Title = "DisplayForm";
}
#using (Html.BeginForm("DisplayForm", "FormController", FormMethod.Post))
{
<form>
<div>
#Html.LabelFor(model => model.Empname)
#Html.TextBoxFor(model => model.Empname)
#* #Html.Hidden("Emplname", Model.Empname)*#
#Html.LabelFor(model => model.EmpId)
#Html.TextBoxFor(model => model.EmpId)
#* #Html.Hidden("Emplid", Model.EmpId)*#
#Html.LabelFor(model => model.EmpDepartment)
#Html.TextBoxFor(model => model.EmpDepartment)
#* #Html.Hidden("Empldepart", Model.EmpDepartment)*#
<input type="button" id="submitId" value="submit" />
</div>
</form>
}
model
public class FormModel
{
public string _EmpName;
public string _EmpId;
public string _EmpDepartment;
public string Empname
{
get {return _EmpName; }
set { _EmpName = value; }
}
public string EmpId
{
get { return _EmpId;}
set {_EmpId =value;}
}
public string EmpDepartment
{
get { return _EmpDepartment; }
set { _EmpDepartment = value; }
}
}
controller
public ActionResult DisplayForm()
{
FormModel frmmdl = new FormModel();
frmmdl.Empname=**How to get the textbox value here from view on submitbutton click???**
}
First you need to change your button type to "submit". so your form values will be submitted to your Action method.
from:
<input type="button" id="submitId" value="submit" />
to:
<input type="submit" id="submitId" value="submit" />
Second you need to add your model as parameter in your Action method.
[HttpPost]
public ActionResult DisplayForm(FormModel model)
{
var strname=model.Empname;
return View();
}
Third, If your Controller name is "FormController". you need to change the parameter of your Html.Beginform in your view to this:
#using (Html.BeginForm("DisplayForm", "Form", FormMethod.Post))
{
//your fields
}
P.S.
If your view is the same name as your Action method which is "DisplayForm" you don't need to add any parameter in the Html.BeginForm. just to make it simple. like so:
#using (Html.BeginForm())
{
//your fields
}
Have an ActionResult for the form post:
[HttpPost]
public ActionResult DisplayForm(FormModel formModel)
{
//do stuff with the formModel
frmmdl.Empname = formModel.Empname;
}
Look into Model Binding. Default model binding will take the data embedded in your posted form values and create an object from them.
Let's implement simple ASP.NET MVC subscription form with email textbox.
Model
The data from the form is mapped to this model
public class SubscribeModel
{
[Required]
public string Email { get; set; }
}
View
View name should match controller method name.
#model App.Models.SubscribeModel
#using (Html.BeginForm("Subscribe", "Home", FormMethod.Post))
{
#Html.TextBoxFor(model => model.Email)
#Html.ValidationMessageFor(model => model.Email)
<button type="submit">Subscribe</button>
}
Controller
Controller is responsible for request processing and returning proper response view.
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Subscribe(SubscribeModel model)
{
if (ModelState.IsValid)
{
//TODO: SubscribeUser(model.Email);
}
return View("Index", model);
}
}
Here is my project structure. Please notice, "Home" views folder matches HomeController name.
You model will be posted as a object on the action and you can get it in action on post like this:
[HttpPost]
public ActionResult DisplayForm(FormModel model)
{
// do whatever needed
string emp = model.EmpName;
}
it you are posting data always put HttpPost attribute on the action.
Your view also has mistakes, make it like this:
#using (Html.BeginForm("DisplayForm", "Form", FormMethod.Post))
{
<div>
#Html.LabelFor(model => model.Empname)
#Html.TextBoxFor(model => model.Empname)
#* #Html.Hidden("Emplname", Model.Empname)*#
#Html.LabelFor(model => model.EmpId)
#Html.TextBoxFor(model => model.EmpId)
#* #Html.Hidden("Emplid", Model.EmpId)*#
#Html.LabelFor(model => model.EmpDepartment)
#Html.TextBoxFor(model => model.EmpDepartment)
#* #Html.Hidden("Empldepart", Model.EmpDepartment)*#
<input type="button" id="submitId" value="submit" />
</div>
}
There are two ways you can do this.
The first uses TryUpdateModel:
public ActionResult DisplayForm()
{
FormModel frmmdl = new FormModel();
TryUpdateModel (frmmdl);
// Your model should now be populated
}
The other, simpler, version is simply to have the model as a parameter on the [HttpPost] version of the action:
[HttpPost]
public ActionResult DisplayForm(FormModel frmmdl)
{
// Your model should now be populated
}
Change your controller like below.
[HttpPost]
public ActionResult DisplayForm(FormModel model)
{
var Empname = model.Empname;
}
You need to have both Get and Post Methods:
[HttpGet]
public ActionResult DisplayForm()
{
FormModel model=new FormModel();
return View(model);
}
[HttpPost]
public ActionResult DisplayForm(FormModel model)
{
var employeeName=model.Empname;
return View();
}
[HttpPost]
public ActionResult DisplayForm(FormModel model)
{
var value1 = model.EmpName;
}
Model values from hidden field? I recommend the strongly typed approach shown below:
public ActionResult DisplayForm(string Emplname, string Emplid, string Empldepart)
[HttpPost]
public ActionResult DisplayForm(FormModel model)
{
FormModel frmmdl = new FormModel();
frmmdl.Empname=**How to get the textbox value here from view on submitbutton //click???**
}
model.Empname will have the value

Categories