I search much but I am not lucky to find the solution, My aim is save a model depending on the button that the user chooses.
I have two inputs of type button, which should each invoke a different method from the controller at the moment of press click. You must have an account. All this happens in the same view for only a model.
This is my view:
#model WebShop.Models.Product
#{
ViewBag.Title = "Create";
}
<h2>Crear</h2>
#using Newtonsoft.Json
#using (Html.BeginForm(new { #id = "create" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Producto</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.ProductNumber, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ProductNumber, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ProductNumber, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ProductTitle, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ProductTitle, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ProductTitle, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Crear" class="btn btn-default" />
<input type="submit" value="Crear en memoria" class="btn btn-default" id="InMemory" />
</div>
</div>
</div>
}
And these are my methods:
[HttpPost]
public ActionResult Create(Product product)
{
try
{
List<Product> listProducts = new List<Product>();
if (ModelState.IsValid)
{
db.Products.Add(product);
db.SaveChanges();
TempData["list"] = db.Products.ToList();
return RedirectToAction("Index");
}
return View(product);
}
catch
{
return View(product);
}
}
[HttpPost]
public ActionResult CreateInMemory(Product product)
{
try
{
if (ModelState.IsValid)
{
using (SQLiteConnection con = new SQLiteConnection("Data Source=:memory:"))
{
con.Open();
if (string.IsNullOrEmpty(result.ToString()))
{
string query = #"CREATE TABLE Products
(ProductID integer primary key,
ProductNumber integer,
ProductTitle varchar(100));";
using (SQLiteCommand comd = new SQLiteCommand(query,con))
{
comd.ExecuteNonQuery();
TempData["list"] = saveListProduct(product, con);
}
}
else
{
TempData["list"] = saveListProduct(product, con);
}
con.Close();
return RedirectToAction("Index");
}
}
return View(product);
}
catch(Exception e)
{
string message = e.Message;
return View("Index");
}
}
In order that they are in context, I want to guard the model in the database and in memory with SQLite, and any suggestion is welcome.
I think you can use formaction attribute (HTML5) for this. Try the following. Hope to help, my friend :))
<input type="submit" name="response" value="Create" formaction=#Url.Action("Create") formmethod="post" class="btn btn-default" />
<input type="submit" name="response" value="CreateInMemory" formaction=#Url.Action("CreateInMemory") formmethod="post" class="btn btn-default" />
Note: It just can be implemented in HTML5.
consider the following sample , how to send a model to different methods of same controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Method1(BooModel model)
{
...
}
[HttpPost]
public ActionResult Method2(BooModel model)
{
...
}
}
public class BooModel
{
public int Id { get; set; }
public string Name { get; set; }
}
#model WebApi.Controllers.BooModel
#using (Html.BeginForm())
{
#Html.TextBoxFor(x=>x.Id)
#Html.TextBoxFor(x=>x.Name)
<input type="submit" value="Method1" onclick='this.form.action="#Url.Action("Method1", "Home", null, this.Request.Url.Scheme)"' />
<input type="submit" value="Method2" onclick='this.form.action="#Url.Action("Method2", "Home", null, this.Request.Url.Scheme)"' />
}
For a jQuery solution change your <input> elements into plain <button> ones and use the below jQuery in your $(document).ready() function :
$("#btnCreate").on('click', function () {
$.ajax({
url: '#Url.Action("Create", "Controller", new { area="Area"})',
type: "POST",
data: $('form').serialize(),
success: function () {
//Go to new location etc
}
})
})
$("#btnCreateInMemory").on('click', function () {
$.ajax({
url: '#Url.Action("CreateInMemory", "Controller", new { area="Area"})',
type: "POST",
data: $('form').serialize(),
success: function () {
//Go to new location etc
}
})
})
Related
I've come up with problem, when trying to fill data to my model. I have an "Resource" entity, which can have no-to-many "attributes". I have templates set up, which holds names for those attributes. When Resource is created, user chooses on of templates, then Attributes are created(empty) and program generates form for those attributes.
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(Model => Model.Resource)
#for (int i = 0; i < Model.Attributes.Count(); i++)
{
<div class="form-group">
#*Html.LabelFor(d => d.Attributes.ToArray()[i].Name, htmlAttributes: new { #class = "control-label col-md-2" })*#
<h4>#Html.Raw(Model.Attributes.ToList()[i].Name)</h4>
<div class="col-md-10">
#Html.TextBoxFor(Model => Model.Attributes.ToList()[i].Value, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(Model => Model.Attributes.ToList()[i].Value, "", new { #class = "text-danger" })
</div>
</div>
}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
This form uses this View model:
public class ResourceAttributesViewModel
{
public virtual Resource Resource { get; set; }
public virtual ICollection<_Attribute> Attributes { get; set; }
}
problem is that when i hit "submit" button, it gives me view model with null Resource and Attributes properties
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Fill(ResourceAttributesViewModel AttributeSet)
{
if(ModelState.IsValid)
{
foreach (var attr in AttributeSet.Attributes)
{
db.Entry(attr).State = EntityState.Modified;
db.SaveChanges();
}
return RedirectToAction("Index");
}
return View(AttributeSet);
}
if it helps, there is POST string sent by browser
__RequestVerificationToken=XoVM9h_3njX5x2m35b_vKKHY3m5UDaYm9_2ZMfNkglouqHJCSw2NO56Tv2Sb3kXy8qC8XBLXawoQv0ft0xc-LxYmQGfi4EAqroq2b63Wb9Q1&Resource=System.Data.Entity.DynamicProxies.Resource_7639327FA0332BEBC7FB6836F70C3D62C3D744D76F2C3F8DDFCE679AA8CA31DC&%5B0%5D.Value=100&%5B1%5D.Value=200
I am redirecting my viewModel from the HttpPost of View1 to the HttpGet of View2.
This works without problems.
There the user has to accept the terms and agreemens.
This should get changed in the viewModel to true (before it is false).
And then redirect to the HttpPost of view2.
There something goes wrong.
The HttpPost ActionResult of View2 receives the viewModel with all Parameters as NULL (before they were filled)
How can I fix this?
Here is my HttpGet ActionResult for View2:
public ActionResult Verify(QuestionViewModel viewModel)
{
//Anrede in Viewbag
if (viewModelVeri.Per_Salutation == 2)
{
ViewBag.Per_Salutation = "Frau";
}
else
{
ViewBag.Per_Salutation = "Herr";
}
int? per_region_id = viewModelVeri.Per_Region;
int per_region_id_nullable = Convert.ToInt32(per_region_id);
Region region = _repository.GetRegionById(per_region_id_nullable);
QuestionViewModel viewModel2 = new QuestionViewModel()
{
Reg_Name = region.Reg_Name
};
//Regionsname in Viewbag
ViewBag.Reg_Name = viewModel2.Reg_Name;
return View(viewModel);
}
And here's my HttpPost ActionResult for View2:
[HttpPost]
public ActionResult Verify(QuestionViewModel viewModel, string tbButton)
{
//here the ViewModel-Parameters are already NULL
My View:
<div class="panel-body">
#using (Html.BeginForm("Verify", "QuestionForm", FormMethod.Post, new { id = "verifyform" }))
{
#Html.AntiForgeryToken()
<div class="ctrl-row">
<div class="form-group">
<div class="container-fluid">
#Html.LabelFor(model => model.Per_Salutation, new { #class = "control-label col-sm-1" })
<div class="col-sm-3">
#ViewBag.Per_Salutation
</div>
</div>
</div>
</div>
<div class="ctrl-row">
<div class="form-group">
<div class="container-fluid">
#Html.LabelFor(model => model.Per_Name_Last, new { #class = "control-label col-sm-1" })
<div class="col-sm-3">
#Html.DisplayFor(model => model.Per_Name_Last, new { #class = "control-label col-sm-1 non-zero-num" })
</div>
#Html.LabelFor(model => model.Per_Name_First, new { #class = "control-label col-sm-1" })
<div class="col-sm-3">
#Html.DisplayFor(model => model.Per_Name_First, new { #class = "control-label col-sm-1 non-zero-num" })
</div>
</div>
</div>
</div
<div class="ctrl-row">
<div class="form-group">
<div class="container-fluid">
#Html.LabelFor(model => model.Per_EMail, new { #class = "control-label col-sm-1" })
<div class="col-sm-8">
#Html.DisplayFor(model => model.Per_EMail, new { #class = "control-label col-sm-1 non-zero-num" })
</div>
</div>
</div>
</div>
<div class="checkbox">
<input type="checkbox" id="NutzungsbedingungenAngenommen " />
<label for="NutzungsbedingungenAngenommen ">
Ich erkläre mich mit den Nutzungsbedingungen einverstanden.
</label>
</div>
<button class="btn btn-default" type="submit" name="tbButton" value="questsend">Senden</button>
}
<script>
$(document).ready(function () {
$(".non-zero-num").val($(this).val() == 0 ? ' ' : $(this).val());
})
$('#verifyform').on('click', '[value="questsend"]', function () {
if ($('#agree').is(':checked')) {
return true;
}
else {
return false;
}
});
</script>
EDIT
Here my QuestionViewModel
public class QuestionViewModel
{
//Other Properties
[Required(ErrorMessage = "Bitte die Nutzungsbedingungen annehmen!")]
public bool NutzungsbedingungenAngenommen { get; set; }
}
My HttpPost Controller for View1:
[HttpPost]
public ActionResult DefaultForm(QuestionViewModel viewModel, string tbButton)
{
if (ModelState.IsValid)
{
try
{
if (tbButton.Equals("questsend"))
{
return RedirectToAction("Verify", viewModel);
}
else if (tbButton.Equals("questupload"))
{
//write to DB
return View(viewModel);
}
else
{
dropdownPopulate(viewModel);
return View("DefaultForm", viewModel);
}
}
catch
{
dropdownPopulate(viewModel);
return View(viewModel);
}
}
else
{
dropdownPopulate(viewModel);
return View(viewModel);
}
}
The problem is you use Html.DisplayFor to display the property values of viewModel in View2, so the values won't be submitted to the HttpPost method, hence viewModel is null when HttpPost for View2 is executed. Only values in <input>, <textarea> and <select> tags will be submitted.
You can submit the values of viewModel to the HttpPost for View2 by adding Html.HiddenFor inside Html.BeginForm for all properties of viewModel. You should also use Html.CheckBoxFor(m => m.NutzungsbedingungenAngenommen) for the checkbox. Something like below should work
#using (Html.BeginForm("Verify", "QuestionForm", FormMethod.Post, new { id = "verifyform" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(m => m.Per_Salutation)
#Html.HiddenFor(m => m.Per_Name_First)
#Html.HiddenFor(m => m.Per_Name_Last)
.... // Html.HiddenFor for the rest of QuestionViewModel properties
....
.... // the rest of your code inside the form tag
.... // remove <input type="checkbox" id="NutzungsbedingungenAngenommen " />
#Html.CheckBoxFor(m => m.NutzungsbedingungenAngenommen)
<button class="btn btn-default" type="submit" name="tbButton" value="questsend">Senden</button>
}
Make sure you declare what model should be used by Razor.
#model QuestionViewModel
Make sure the name and id of your HTML inputs are in the format expected by the MVC modelbinder. I recommend using the provided HtmlHelpers instead of writing the input tags by hand.
#Html.CheckBoxFor(m => m.Agree)
Remove the string tbButton parameter from your POST action
I need two models in my view, so I created ViewModel that combines them. That is on getting method. But on the Post, my input type=submit is returning ViewModel, but values of properties inside are null. Any advice?
These are my actions for Get and Post
[HttpGet]
public ActionResult Report(int id)
{
using (SkolskaBibliotekaDBModel db = new SkolskaBibliotekaDBModel())
{
ReportZaPrikaz RZP = new ReportZaPrikaz();
var komentar = db.Komentar.FirstOrDefault(x => x.KomentarID == id);
RZP.kzp = new KomentarZaPrikaz()
{
KomentarID = komentar.KomentarID,
KomentarText = komentar.KomentarText,
KorisnikID = komentar.KorisnikID,
Reported = komentar.Reported,
VremeKomentara = komentar.VremeKomentara,
Ime = komentar.Korisnik.Ime,
Prezime = komentar.Korisnik.Prezime,
PicPath = komentar.Korisnik.PicPath,
VoteUp = komentar.VoteUp,
VoteDown = komentar.VoteDown
};
RZP.report = db.PrijavaKomentara.Create();
return View("Report",RZP);
}
}
[HttpPost]
public void Report(ReportZaPrikaz RZP)
{
using (SkolskaBibliotekaDBModel db = new SkolskaBibliotekaDBModel())
{
db.PrijavaKomentara.Add(RZP.report);
db.SaveChanges();
}
}
this is my viewmodel:
namespace SkolskaBiblioteka.ViewModels
{
public class ReportZaPrikaz
{
public KomentarZaPrikaz kzp;
public PrijavaKomentara report;
}
}
and this is my view:
#model SkolskaBiblioteka.ViewModels.ReportZaPrikaz
#using SkolskaBiblioteka.ViewModels
#{
ViewBag.Title = "Пријава коментара";
}
<div class="container">
#Html.Partial("_Komentar", Model.kzp)
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>PrijavaKomentara</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#{
Model.report.KorisnikId = ((KorisnikZaPrikaz)Session["Korisnik"]).KorisnikId;
}
#Html.HiddenFor(x => x.report.KorisnikId)
#{
Model.report.KomentarId = Model.kzp.KomentarID;
}
#Html.HiddenFor(x => x.report.KomentarId)
#{
Model.report.VremePrijave = DateTime.Now;
}
#Html.HiddenFor(x => x.report.VremePrijave)
<div class="form-group">
#Html.LabelFor(model => model.report.Tekst, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.report.Tekst, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
</div>
These conditions show up when I hit submit button.
The default model-binder would not bind fields. Try to use properties instead:
public class ReportZaPrikaz
{
public KomentarZaPrikaz kzp { get; set; }
public PrijavaKomentara report { get; set; }
}
I am setting up a view and ViewModel to accept some data and a File. But when I look at the returned model, I do not see a file.
Here's my ViewModel:
public class ResourceReviewViewModel
{
public Guid ResourceReviewId { get; set; }
//....
[Display(Name="Review Document File")]
public HttpPostedFileBase ReviewFile { get; set; }
}
My view:
My controller to handle the submit:
[HttpPost]
[ValidateAntiForgeryToken]
public virtual ActionResult ResourceReview(ResourceReviewViewModel model)
{
//...
return View(model); // model.ReviewFile is null
}
#model PublicationSystem.ViewModels.ResourceReviewViewModel
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Submit Your Review</h4>
<hr/>
#Html.HiddenFor(model => model.RequestReviewId, new { htmlAttributes = new { #class = "form-control" } })
<div class="form-group">
#Html.LabelFor(model => model.ReviewFile, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<input type="file" id="ReviewFile" name="ReviewFile" value="ActionHandlerForForm" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Submit" class="btn btn-default" />
</div>
</div>
</div>
}
The model comes back with values, but the file property is NULL. The HTML for the Input I copied from another page, so I'm not sure I need value="ActionHandlerForForm".
Yes, it's possible. I think in your example you're just missing multipart/form-data
Try this (replace "Index" and "Home" to the View/Controller you have):
#using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
...
}
I have a textbox input and some radio buttons. For example my textbox input HTML looks like that:
<input type="text" name="IP" id="IP" />
Once user clicks a button on a web page I want to pass data to my controller:
<input type="button" name="Add" value="#Resource.ButtonTitleAdd" onclick="location.href='#Url.Action("Add", "Configure", new { ipValue =#[ValueOfTextBox], TypeId = 1 })'"/>
Maybe it is trivial but my problem is that I do not know how to get textbox value and pass it through to the controller. How can I read the textbox value and pass it to the controller through ipValue=#[ValueOfTextBox]?
Simple ASP.NET MVC subscription form with email textbox would be implemented like that:
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 may use jQuery:
<input type="text" name="IP" id="IP" value=""/>
#Html.ActionLink(#Resource.ButtonTitleAdd, "Add", "Configure", new { ipValue ="xxx", TypeId = "1" }, new {#class = "link"})
<script>
$(function () {
$('.link').click(function () {
var ipvalue = $("#IP").val();
this.href = this.href.replace("xxx", ipvalue);
});
});
</script>
Try This.
View:
#using (Html.BeginForm("Login", "Accounts", FormMethod.Post))
{
<input type="text" name="IP" id="IP" />
<input type="text" name="Name" id="Name" />
<input type="submit" value="Login" />
}
Controller:
[HttpPost]
public ActionResult Login(string IP, string Name)
{
string s1=IP;//
string s2=Name;//
}
If you can use model class
[HttpPost]
public ActionResult Login(ModelClassName obj)
{
string s1=obj.IP;//
string s2=obj.Name;//
}
Another way by using ajax method:
View:
#Html.TextBox("txtValue", null, new { placeholder = "Input value" })
<input type="button" value="Start" id="btnStart" />
<script>
$(function () {
$('#btnStart').unbind('click');
$('#btnStart').on('click', function () {
$.ajax({
url: "/yourControllerName/yourMethod",
type: 'POST',
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: JSON.stringify({
txtValue: $("#txtValue").val()
}),
async: false
});
});
});
</script>
Controller:
[HttpPost]
public EmptyResult YourMethod(string txtValue)
{
// do what you want with txtValue
...
}
you can do it so simple:
First: For Example in Models you have User.cs with this implementation
public class User
{
public string username { get; set; }
public string age { get; set; }
}
We are passing the empty model to user – This model would be filled with user’s data when he submits the form like this
public ActionResult Add()
{
var model = new User();
return View(model);
}
When you return the View by empty User as model, it maps with the structure of the form that you implemented. We have this on HTML side:
#model MyApp.Models.Student
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Student</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.username, htmlAttributes: new {
#class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.username, new {
htmlAttributes = new { #class = "form-
control" } })
#Html.ValidationMessageFor(model => model.userame, "",
new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.age, htmlAttributes: new { #class
= "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.age, new { htmlAttributes =
new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.age, "", new {
#class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default"
/>
</div>
</div>
</div>
}
So on button submit you will use it like this
[HttpPost]
public ActionResult Add(User user)
{
// now user.username has the value that user entered on form
}