I am trying to post an item to a collection that belongs to another model.
This is the form in the view:
#using (Html.BeginForm("Create", "Comment", FormMethod.Post, new { enctype = "multipart/form-data", encoding = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="modal-body">
<div class="form-horizontal">
<input type="hidden" value="#Model.DeviceID" />
<div class="form-group">
<h5>Your name</h5>
<div class="col-md-10">
<input name="Author" />
</div>
</div>
<div class="form-group">
<h5>Comment</h5>
<div class="col-md-10">
<textarea name="Comment"></textarea>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-primary" value="Submit" /> <!--Next</input>-->
</div>
}
and the controller code is set up as follows
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(string returnUrl, int devID, string Author, string text)
{
string url = this.Request.UrlReferrer.AbsolutePath;
Comment comment = new Comment();
if (ModelState.IsValid)
{
//db.Comments.Add(comment);
db.SaveChanges();
return Redirect(url);
}
return Redirect(url);
}
However this doesnt work because I cant set the model id of the item that is getting posted.
What is the Asp.net MVC way to add to a virtual collection that a model owns?
What I have noticed the names don't match in your controller. So you don't retrieve it well.
Change first this line:
<input name="Author" /> and <textarea name="Comment"></textarea>
By:
<input name="author" /> and <textarea name="comments"></textarea>
Could you change the parameters to match the name from the view.
public ActionResult Create(string returnUrl, int DeviceID, string author, string comments)
{
string url = this.Request.UrlReferrer.AbsolutePath;
Comment myComment = new Comment();
comment.DeviceID = DeviceID;
comment.Author = author;
comment.Comments= comments;// I presume your Comment class has thoses properties if not you can see at least the way you can deal with that
if (ModelState.IsValid)
{
db.Comments.Add(myComment);
db.SaveChanges();
return Redirect(url);
}
return Redirect(url);
}
I hope it will help. If you can show the code of your Comment model so I can edit that if it requires.
Related
I've been working on a large project for a few days. Its all finished except for this part. I'm trying to pass 2 text boxes into my home controller method.
I've tried to use "model." and "item." but with no luck. it always passes null
<p>
#Html.ActionLink("Display", "Home", FormMethod.Post)
</p>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div>
Month:<input type="text" name="Month" id="MonthInput">
Extra:<input type="text" name="Extra" id="ExtraInput"><br /><br />
<input type="submit" value="Add" class="btn btn-default"> <br> <br>
</div>
}
and in the home controller is
[HttpPost]
public ActionResult Display(String Month, String Extra)
{
if (ModelState.IsValid)
{
...
return RedirectToAction("Index");
}
return view;
}
I want it to pass whatever value is typed in the textboxes when the "Add" Button is clicked but it gives null
try this,
In View
#using (Html.BeginForm("Display", "Home", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div>
Month:<input type="text" name="Month" id="MonthInput">
Extra:<input type="text" name="Extra" id="ExtraInput"><br /><br />
<input type="submit" value="Add" class="btn btn-default"> <br> <br>
</div>
}
In Controller,
[HttpPost]
public ActionResult Display(SomeClass someClass)
{
if (ModelState.IsValid)
{
...
return RedirectToAction("Index");
}
return view;
}
Create Normal class name SomeClass, name as per your requirment,
public class SomeClass{
public string Month {get;set;}
public string Extra {get;set;}
}
the name attribute of inputs should match to properties of SomeClass, it will map automatically, you then can access the value by using someClass object
someClass.Month and someClass.Extra
In order to correctly map to the action's parameters, you must use the name attribute.
#using (Html.BeginForm("Display", "Home"))
{
#Html.AntiForgeryToken()
<div>
Month:<input type="text" name="Month" id="MonthInput">
Extra:<input type="text" name="Extra" id="ExtraInput"><br /><br />
<input type="submit" value="Add" class="btn btn-default">
</div>
}
Totally unrelated, but it seems you have 2 nested forms and one of them POSTs to a php page. Is that desired?
Also, remove the following code because it does not make any sense:
<p>
#Html.ActionLink("Display", "Home", FormMethod.Post)
</p>
To add on to the previous answer, I would suggest accepting the form as a FormCollection in the controller, because the form does not seem to be tied to the model:
[HttpPost]
public ActionResult Display(FormCollection collection)
{
if (ModelState.IsValid)
{
string month = collection["Month"];
string extra = collection["Extra"];
return RedirectToAction("Index");
}
return View();
}
namespace Your.Models
{
public class DisplayModel
{
public string Month {get;set;}
public string Extra {get;set;}
}
}
[HttpPost]
public ActionResult Display(DisplayModel model)
{
if (ModelState.IsValid)
{
string month = model.Month;
string extra = model.Extra;
return RedirectToAction("Index");
}
return View();
}
#using Your.Models
#model DisplayModel
#using (Html.BeginForm("Display", "Home", new { id="displayview" }))
{
#Html.AntiForgeryToken()
<div>
Month:<input type="text" name="Month" id="MonthInput">
Extra:<input type="text" name="Extra" id="ExtraInput"><br /><br />
<input type="submit" value="Add" class="btn btn-default">
</div>
}
I have a Search Partial View that I want to return but I want to return it by running it through an exisiting Partial View Result in the Controller instead of loading the view directly.
So, in the controller I have:
public ActionResult Index()
{
return View();
}
public PartialViewResult _GetSearch(List<Search> model)
{
return PartialView("_Search", model);
}
[ValidateAntiForgeryToken()]
public PartialViewResult _BeginSearch(string search)
{
var results = SearchModels(search).ToList();
return PartialView("_GetSearch", results);
}
And in the search view itself I have:
<div class="col-md-4">
<div id="modelSearch" class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-search"></i> Search by Model / Manufacturer</h3>
</div>
<div class="panel-body">
#using (Ajax.BeginForm("_BeginSearch", "Home", new AjaxOptions() { UpdateTargetId = "modelSearch" }))
{
#Html.AntiForgeryToken()
<div class="input-group">
#Html.TextBox("search", null, new {id = "name", #class = "form-control", placeholder = "Please enter a manufacturer or model"})
<span class="input-group-btn">
<button id="search" class="btn btn-default" type="submit"><i class="fa fa-search"></i></button>
</span>
</div>
if (Model != null)
{
<div class="searchResults fade">
#foreach (var s in Model)
{
<div class="result">
#switch (s.ResultType)
{
case "Man":
#s.Manufacturer
break;
case "Mod":
#s.Manufacturer #s.Model
<img src="~/Images/General/(#s.TierId).png" alt="Tier #s.TierId"/>
break;
}
</div>
}
</div>
}
}
</div>
</div>
</div>
When I try and run the code it tell me that it cannot find the _GetSearch view, which yes technically is right, but I'm not looking for a view I'm looking for a method in the controller.
I'm having a problem in my MVC project. When trying to create an object to add it to the db, it always returns null.
public class ListsModel
{
public EntitiesList EntityList { get; set; }
public List<string> AllGroups { get; set; }
}
public ActionResult Create()
{
ListsModel model = new ListsModel();
model.EntityList = new EntitiesList();
model.AllGroups = managerLists.GetAllListsKeys(); //For droplist
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ListsModel model)
{
if (ModelState.IsValid)
{
model.EntityList.List_CreatedTime = DateTime.Now;
managerLists.AddNewObject(model.EntityList);
return RedirectToAction("Index");
}
return View(model);
}
And a simple cshtml:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>EntitiesList</legend>
<div class="form-group">
#Html.LabelFor(model => model.EntityList.List_EntitityName)
#Html.DropDownListFor(model => model.AllGroups, new SelectList(Model.AllGroups),
new { #class = "form-control" })
<p class="help-block">#Html.ValidationMessageFor(model => model.EntityList.List_EntitityName)</p>
</div>
<div class="form-group">
#Html.LabelFor(model => model.EntityList.List_EntityValue)
<input class="form-control" value="#Model.EntityList.List_EntityValue"/>
<p class="help-block">#Html.ValidationMessageFor(model => model.EntityList.List_EntityValue)</p>
</div>
<div class="form-group">
#Html.LabelFor(model => model.EntityList.List_OrderByNumber)
<input class="form-control" value="#Model.EntityList.List_OrderByNumber"/>
<p class="help-block">#Html.ValidationMessageFor(model => model.EntityList.List_OrderByNumber)</p>
</div>
<div class="form-group">
#Html.LabelFor(model => model.EntityList.List_Comments)
<textarea class="form-control" rows="3">#Model.EntityList.List_Comments</textarea>
<p class="help-block">#Html.ValidationMessageFor(model => model.EntityList.List_Comments)</p>
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
When it's getting to the "model.EntityList.List_CreatedTime = DateTime.Now;" a null reference exception is thrown.
I tried to change the signature to "public ActionResult Create(ListsModel ListsModel)", as suggested here: Create view is posting null objects
But I got the same results.
Hope you can help me.
I think the problem is the way you define inputs like this:
<input class="form-control" value="#Model.EntityList.List_EntityValue"/>
For ASP MVC can collect form data, inputs should have an Name attribute corresponding with model fields.
Try to generate inputs using the standard:
#Html.TextBoxFor(model => model.EntityList.List_EntityValue)
I suggest you inspect the differences in the html generated (to see how is asp mvc generating inputs).
I have troubles with binding my button to an action. I created a form and when user click "send" button it needs to trigger some action.
Below you can see my cshtml code:
#model Project.Models.MailMessage
<form name="contactForm" method="post" action="" class="form-horizontal" role="form">
<div class="col-lg-8">
<div id="Contact" class="jumbotron contact-form">
<div class="panel-heading">
<h1 class="panel-title">Kontakt</h1>
</div>
<div class="input-group">
<span class="input-group-addon">Imie</span>
#Html.TextBoxFor(model => model.Name, new { #class = "form-control" ,placeholder ="Twoje imię"})
<!--<input type="text" class="form-control" placeholder="Imie" id="inputName" required="required">-->
</div>
<div class="input-group">
<span class="input-group-addon">Nazwisko</span>
#Html.TextBoxFor(model => model.Surname, new { #class = "form-control", placeholder = "Twoje nazwisko" })
<!--<input type="text" class="form-control" placeholder="Nazwisko" id="inputSurname" required="required">-->
</div>
<div class="input-group">
<span class="input-group-addon">Email</span>
#Html.TextBoxFor(model => model.EmailAdress, new { #class = "form-control", placeholder = "Adres email" })
<!--<input type="email" class="form-control" placeholder="Email" id="inputEmail" required="required">-->
</div>
<div class="input-group">
<span class="input-group-addon">Treść<br /> wiadomości</span>
#Html.TextAreaFor(model => model.Name, new { #class = "form-control", placeholder = "Treść wiadomości", id = "inputMessage", name = "inputMessage", rows="4" })
<!--<textarea class="form-control" rows="4" id="inputMessage" name="inputMessage" placeholder="Treść wiadomości..." required="required"></textarea>-->
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-1">
<button type="submit" class="btn btn-default">
Send Message
</button>
</div>
</div>
</div>
</div>
</form>
Here is my Controller:
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
// GETL /Search/
public ActionResult Search()
{
return View();
}
public ActionResult Contact()
{
return View();
}
public ActionResult SendMail(MailMessage m)
{
return RedirectToAction("Contact");
}
}
I managed to do all this things. All code works. But stucked with I think easies part tof a job. Binding button to call SendMail(MailMessage m) from Controller.
Can anyone suggest me how to do this?
Use Html.BeginForm helper and <input type="submit" value="..." /> within. See an example here. Prefer infrastructure helpers over own HTML code where possible. You probably do not use Antiforgery mechanics to prevent CSRF attacks. It's recommended in post forms, as described in the example.
You have to declare the action of the form.
<form ... action="#Url.Action("SendMail","Home")" ...>
Try this:
SendMail.cshtml
#model Project.Models.MailMessage
<form name="contactForm" method="post" action="" class="form-horizontal" role="form">
<div class="col-lg-8">
<div id="Contact" class="jumbotron contact-form">
<div class="panel-heading">
<h1 class="panel-title">Kontakt</h1>
</div>
<div class="input-group">
<span class="input-group-addon">Imie</span>
#Html.TextBoxFor(model => model.Name, new { #class = "form-control" ,placeholder ="Twoje imię"})
<!--<input type="text" class="form-control" placeholder="Imie" id="inputName" required="required">-->
</div>
<div class="input-group">
<span class="input-group-addon">Nazwisko</span>
#Html.TextBoxFor(model => model.Surname, new { #class = "form-control", placeholder = "Twoje nazwisko" })
<!--<input type="text" class="form-control" placeholder="Nazwisko" id="inputSurname" required="required">-->
</div>
<div class="input-group">
<span class="input-group-addon">Email</span>
#Html.TextBoxFor(model => model.EmailAdress, new { #class = "form-control", placeholder = "Adres email" })
<!--<input type="email" class="form-control" placeholder="Email" id="inputEmail" required="required">-->
</div>
<div class="input-group">
<span class="input-group-addon">Treść<br /> wiadomości</span>
#Html.TextAreaFor(model => model.Name, new { #class = "form-control", placeholder = "Treść wiadomości", id = "inputMessage", name = "inputMessage", rows="4" })
<!--<textarea class="form-control" rows="4" id="inputMessage" name="inputMessage" placeholder="Treść wiadomości..." required="required"></textarea>-->
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-1">
<button type="submit" class="btn btn-default">
Send Message
</button>
</div>
</div>
</div>
</div>
</form>
Here you controller
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
// GETL /Search/
public ActionResult Search()
{
return View();
}
public ActionResult Contact()
{
return View();
}
[HttpGet]
public ActionResult SendMail(MailMessage m)
{
return View();
}
[HttpPost]
public ActionResult SendMail(MailMessage m)
{
return RedirectToAction("Contact");
}
}
When you click on button it call [HttpPost] Method in you controller. It is necessary to mention [HttpPost]
just change your method
[HttpPost]
public ActionResult SendMail(MailMessage m)
{
return RedirectToAction("Contact");
}
I am new to MVC and I am stuck in creating a submit form.
Model Email.cs:
using System.Web;
namespace MySite.Models
{
public class Email
{
public string From { get; set; }
public string Subject { get; set; }
public string body { get; set; }
}
}
Controller CommunicationController.cs:
namespace MySite.Controllers
{
public class CommunicationController : Controller
{
public ActionResult SendEmail() {
Email email = new Email();
return View(email);
}
[HttpPost]
public ActionResult SendEmail(Email email)
{
if (ModelState.IsValid)
{
}
return View(email);
}
}
}
View SendEmail.cshtml:
#model MySite.Models.Email
#{
ViewBag.Title = "SendEmail";
}
<h2>#Html.Label("Send email")</h2>
#using(Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="editor-label">
#Html.Label("From")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.From)
</div> <div class="editor-label">
#Html.Label("Subject")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Subject)
</div> <div class="editor-label">
#Html.Label("Body")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.body)
</div>
<input id="btnSubmit" type="submit" value="SendEmail" />
}
When I press submit, the event never gets fired. In the controller if I press 'go to view' then it goes to SendEmail view. I have no idea whats happenning. I tried to debug but the [HttpPost] controller never gets fired.
Here is what I get from browser, I don't see action
<form method="post" action="/" novalidate="novalidate">
<input type="hidden" value="ZktM_I7fzdlcNme4YVEcNNpnFFmQu1cpAuTXarO_V4w-7bPmpHkaLRfNY3cXGMYy7wkRgSJWWSkS8lp5vdRimFrNCgqk0Jfdr4v7Zc3V2pg1" name="__RequestVerificationToken">
<div class="editor-label">
<div class="editor-field">
<input id="From" class="text-box single-line" type="text" value="" name="From">
</div>
<div class="editor-label">
<div class="editor-field">
<div class="editor-label">
<div class="editor-field">
<input id="btnSubmit" type="submit" value="SendEmail">
</form>
Try this,
#using (Html.BeginForm("ActionName", "ControllerName",
FormMethod.Post))
{
//form UI
<input id="btnSubmit" type="submit" value="SendEmail" />
}
Edit
You can also try this:
<a onclick="$('#formId').submit();">Submit</a>
or
<button type="submit">Submit</button>
I rarely use the basic helper, so I could be wrong, but I believe the default method you get from
Html.BeginForm()
is a GET. So, you probably want to use
Html.BeginForm("SendEmail", "Communication", FormMethod.Post, new { /* html attributes */ })
Then, to test whether you're actually hitting the controller, add this inside the action:
ModelState.AddModelError("", "Action was called!");
That will show up as an error in your ValidationSummary, which is okay, since we're just debugging here.
I'm a little late to the party...
Try replacing:
<input id="btnSubmit" type="submit" value="SendEmail" />
With:
<button id="btnSubmit" type="submit" name="submitButton value="SendEmail" />
Let us know if this works, or if you found another solution! :)