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).
Related
My View Model
public class PostViewModel
{
public Post Post { get; set; }
public IEnumerable<Comment> Comments { get; set; }
}
In my razor view I am trying to get data for my comment
#using (Html.BeginForm("Comment", "Post"))
{
<div class="form-group">
#Html.LabelFor(m => m.Comments.Data);
#Html.TextAreaFor(m => m.Comments.Data, new { #class = "form-control" })
</div>
#Html.HiddenFor(m => m.Comments.Id)
<button type="submit" class="btn btn-primary"> Comment </button>
}
But I am getting errors
then I tried the following syntax
#using (Html.BeginForm("Comment", "Post"))
{
#foreach(var comment in Model.Comments)
{
<div class="form-group">
#Html.LabelFor(comment.Data);
#Html.TextAreaFor(comment.Data, new { #class = "form-control" })
</div>
#Html.HiddenFor(comment.Id)
<button type="submit" class="btn btn-primary"> Comment </button>
}
}
But I am still getting errors
actually I am doing a blog project
So, I am hoping to have Post, all old comment and new comment button in a Details page
Your lambda syntax is wrong. The following will compile and work but the values won't be posted back to the controller action:
#foreach(var comment in Model.Comments)
{
#Html.LabelFor(x=> comment.Data)
}
Secondly, for posting collection back to action it should be done in a for loop with index named controls as the model binder binds it back to collection using the names of the input control that will not be generated in the format which model binder needs.
Do like:
#for(int i=0; i < Model.Comments.Count(); i++)
{
<div class="form-group">
#Html.LabelFor(x => Model.Comments[i].Data);
#Html.TextAreaFor(x => Model.Comments[i].Data, new { #class = "form-control" })
</div>
#Html.HiddenFor(x => Model.Comments[i].Id)
<button type="submit" class="btn btn-primary"> Comment </button>
}
Ehsan Sajjad Made me understand that we can write lambda expression like this
#Html.LabelFor(x=> comment.Data)
later I solved my problem, actually my approach was quite wrong
for solving my problem I add another component NewComment in my ViewModel
public class PostViewModel
{
public Post Post { get; set; }
public IEnumerable<Comment> Comments { get; set; }
public Comment NewComment { get; set; } // this is new addition
}
Then My New Comment area is like the following in the razor syntax
#using (Html.BeginForm("Comment", "Post", Model.Post))
{
var comment = Model.NewComment;
<div class="form-group">
#Html.LabelFor(m => comment.Data);
#Html.TextAreaFor(m => comment.Data, new { #class = "form-control" })
</div>
#Html.HiddenFor(m => comment.Id)
<button type="submit" class="btn btn-primary"> Comment </button>
}
I am doing a project where in Details view
Firstly, Appeared a Post
Secondly, It's comment
Thirdly, A section for it's new comment
Full code for it's details page
#model SimpleBlog.Models.PostViewModel
#{
ViewBag.Title = "Details";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#*Post Section*#
<div class="jumbotron">
<h1> #Model.Post.Title </h1>
<p class="lead"> #Model.Post.PostedBy </p>
<p> #Model.Post.PostDate.ToString("d MMM yyyy") </p>
</div>
<br />
<div class="jumbotron">
<p class="lead"> #Model.Post.Body </p>
</div>
#* Old comments section *#
#foreach (var comment in Model.Comments)
{
<h4> #comment.CommentBy </h4>
<h4> #comment.CommentDate.ToString("d MMM yyyy") </h4>
<h4> #comment.Data </h4>
<br />
<br />
}
#* New Comment section *#
#using (Html.BeginForm("Comment", "Post", Model.Post))
{
var comment = Model.NewComment;
<div class="form-group">
#Html.LabelFor(m => comment.Data);
#Html.TextAreaFor(m => comment.Data, new { #class = "form-control" })
</div>
#Html.HiddenFor(m => comment.Id)
<button type="submit" class="btn btn-primary"> Comment </button>
}
I have the following:
#model Pharma.ViewModels.SearchBoxViewModel
<div class="smart-search">
#using (Html.BeginForm("Index", "Search", FormMethod.Get, new { #class = "form-horizontal", role = "form" }))
{
<div class="form-group">
<div class="hidden-xs- col-sm-1 col-md-1 col-lg-1 text-right">
#Html.LabelFor(m => m.SearchPhrase, new { #class = "control-label" })
</div>
<div class="col-xs-8 col-sm-8 col-md-9 col-lg-10">
#Html.TextBoxFor(m => m.SearchPhrase, new { #class = "form-control" })
</div>
<div class="col-xs-4 col-sm-3 col-md-2 col-lg-1">
<input type="submit" value="Search" class="btn btn-default" />
</div>
</div>
}
</div>
As you can see this is creating an input element.
The view model passed to the view contains the following:
public class SearchBoxViewModel
{
[Required]
[Display(Name = "Search")]
public string SearchPhrase { get; set; }
}
At the moment the input element contains a name attribute with the value of "SearchPhrase" but I would like the value to be just "q" without renaming the property.
I would prefer an extension which allows me to call TextBoxFor but without the need of having to supply the Name property, so that the custom attribute somehow sets the value of the Name property automatically to the value specified in the custom attribute.
The following is an example of what I mean:
public class SearchBoxViewModel
{
[Required]
[Display(Name = "Search")]
[Input(Name = "q")]
public string SearchPhrase { get; set; }
}
Combined with:
#model Pharma.ViewModels.SearchBoxViewModel
<div class="smart-search">
#using (Html.BeginForm("Index", "Search", FormMethod.Get, new { #class = "form-horizontal", role = "form" }))
{
<div class="form-group">
<div class="hidden-xs- col-sm-1 col-md-1 col-lg-1 text-right">
#Html.LabelFor(m => m.SearchPhrase, new { #class = "control-label" })
</div>
<div class="col-xs-8 col-sm-8 col-md-9 col-lg-10">
#Html.TextBoxFor(m => m.SearchPhrase, new { #class = "form-control" })
</div>
<div class="col-xs-4 col-sm-3 col-md-2 col-lg-1">
<input type="submit" value="Search" class="btn btn-default" />
</div>
</div>
}
</div>
Which would then produce something similar to the following:
<div class="smart-search">
<form action="/Search/Index" method="get" class="form-horizontal" role="form">
<div class="form-group">
<div class="hidden-xs- col-sm-1 col-md-1 col-lg-1 text-right">
<label for="Search" class="control-label">Search</label>
</div>
<div class="col-xs-8 col-sm-8 col-md-9 col-lg-10">
<input type="text" name="q" id="Search" value="" class="form-control" />
</div>
<div class="col-xs-4 col-sm-3 col-md-2 col-lg-1">
<input type="submit" value="Search" class="btn btn-default" />
</div>
</div>
</form>
</div>
I would like this custom attribute to take effect whenever the SearchBoxViewModel is used regardless of what template is used to prevent errors, with the intention of being clear to programmers, while creating a user-friendly query string for the user.
Is it possible to do this using a custom attribute on the SearchPhrase property in a similar fashion to how the display name is changed?
I wrote something simple but can be a start to write the complete solution.
First I wrote a simple Attribute with the name you provided:
public class InputAttribute : Attribute
{
public string Name { get; set; }
}
Then I wrote a Html helper that wraps default TextBoxFor and searches for Input attribute and if any, It will replace name attribute of generated HtmlString from TextBoxFor:
public static MvcHtmlString MyTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, System.Linq.Expressions.Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
{
var memberExpression = expression.Body as MemberExpression;
var attr = memberExpression.Member.GetCustomAttribute(typeof (InputAttribute)) as InputAttribute;
var result = htmlHelper.TextBoxFor(expression, htmlAttributes);
if (attr != null)
{
var resultStr = result.ToString();
var match = Regex.Match(resultStr, "name=\\\"\\w+\\\"");
return new MvcHtmlString(resultStr.Replace(match.Value, "name=\"" + attr.Name + "\""));
}
return result;
}
Then use this html helper in razor views:
#Html.MyTextBoxFor(m => m.SearchPhrase, new { #class = "form-control" })
Also your model is as follows:
public class SearchBoxViewModel
{
[Required]
[Display(Name = "Search")]
[Input(Name = "q")]
public string SearchPhrase { get; set; }
}
This is a way to complete solution:
You have to implement all of the overloads of TextBoxFor
If you try to send form data to an action with parameter of type SearchBoxViewModel you will get a 404 because ModelBinder can not bind request parameters to this ViewModel. So you will have to write a ModelBinder to solve this problem.
You have to write LabelFor accordingly to match for attribute correctly.
EDIT: In case of your problem you don't have to deal with case 2 because you send a GET request and you will get the form parameters in query string. So you may write your action signature like:
public ActionResult Search(string q)
{
// use q to search
}
The problem occurs when you have a non-primitive type in your action parameters. In this case ModelBinder tries to match query string items (Or request payload) with properties of type of action parameter. For example:
public ActionResult Search(SearchBoxViewModel vm)
{
// ...
}
In this case, query string (or request payload) has your search query in a parameter named q (because name of input is q and html form sends request in form of key-values consist of input name and input value). So MVC can not bind q to SearchPhrase in LoginViewModel and you will get a 404.
I know this isn't what you are explicitly asking for but I feel that having a different ViewModel name from the actual form name undermines one of the core conventions in MVC and may be misleading.
As an alternative, you can just add a new property to the VM that mirrors SearchPhrase and has the proper name:
public class SearchBoxViewModel
{
[Required]
[Display(Name = "Search")]
public string SearchPhrase { get; set; }
[Display(Name = "Search")]
public string q
{
get { return SearchPhrase; }
set { SearchPhrase = value; }
}
}
Change your view to use these:
#model Pharma.ViewModels.SearchBoxViewModel
<div class="smart-search">
#using (Html.BeginForm("Index", "Search", FormMethod.Get, new { #class = "form-horizontal", role = "form" }))
{
<div class="form-group">
<div class="hidden-xs- col-sm-1 col-md-1 col-lg-1 text-right">
#Html.LabelFor(m => m.q, new { #class = "control-label" })
</div>
<div class="col-xs-8 col-sm-8 col-md-9 col-lg-10">
#Html.TextBoxFor(m => m.q, new { #class = "form-control" })
</div>
<div class="col-xs-4 col-sm-3 col-md-2 col-lg-1">
<input type="submit" value="Search" class="btn btn-default" />
</div>
</div>
}
</div>
This would allow you to keep your code in the back end referencing SearchPhrase instead of q to make it easier on the programmers. Hopefully this view isn't spread out everywhere and you only have a single EditorTemplate or partial.
Been searching around but couldn't find a direct solution to what I'm trying to achieve.
I've tried to include as much as needed but it's a very large project so hopefully you'll get the gist.
Overview:
I have a view model that has several lists of objects within it. I am using two partial views for control over each of the list of objects, one for gathering the list of objects (which is held in a session), and the other for adding a list of said object into the list.
Update:
As per comment - what I am looking to do is as follows - in the Index, fill out the existingIp model info, which is displayed through the addToListPartialView, then it will post to the ListPartialView to update the list through the session, handled backend in the controller, which will in turn display on the Index - the question ultimately is, how do I achieve this?
Problem:
The issue I'm having is once I've added an object, through a partial view, to the object list, another partial view, how do I then pass this back to the main view?
Code:
Controller
public ActionResult AddExistingIp([Bind(Include = "Subnet, Cidr, Mask")]ExistingIp existingIp)
{
if(Session["pa_ipv4Session"] != null)
{
pa_ipv4 pa_ipv4 = (pa_ipv4)Session["pa_ipv4Session"];
if(pa_ipv4.ExistingIps == null)
{
pa_ipv4.ExistingIps = new List<ExistingIp>();
}
pa_ipv4.ExistingIps.Add(existingIp);
ViewBag.pa_ipv4 = pa_ipv4.ExistingIps;
return View("ExistingIpView", ViewBag.pa_ipv4);
}
else
{
pa_ipv4 pa_ipv4 = new pa_ipv4();
Session["pa_ipv4Session"] = pa_ipv4;
pa_ipv4.ExistingIps = new List<ExistingIp>();
pa_ipv4.ExistingIps.Add(existingIp);
ViewBag.pa_ipv4 = pa_ipv4.ExistingIps;
return View("ExistingIpView", ViewBag.pa_ipv4);
}
Index:
#model ViewModel
<div id="ExistingIpList">
#{Html.RenderPartial("ExistingIpView");}
</div>
<div id="addExisting">
#{Html.RenderPartial("AddExistingIp");}
</div>
List Partial
#model IEnumerable<ExistingIp>
#if (Model != null)
{
foreach (var ei in Model)
{
<div class="ui-grid-c ui-responsive">
<div class="ui-block-a">
<span>#ei.Subnet</span>
</div>
<div class="ui-block-b">
<span>#ei.Cidr</span>
</div>
<div class="ui-block-c">
<span>#ei.Mask</span>
</div>
<div class="ui-block-d">
#ei.Id
Delete
</div>
</div>
}
}
Add to list partial:
#using (Html.BeginForm("AddExistingIp", "PA_IPV4"))
{
<div class="ui-grid-c ui-responsive">
<div class="ui-block-a">
<span>
#Html.EditorFor(m => m.Subnet)
#Html.ValidationMessageFor(m => m.Subnet)
</span>
</div>
<div class="ui-block-b">
<span>
#Html.EditorFor(m => m.Cidr)
#Html.ValidationMessageFor(m => m.Cidr)
</span>
</div>
<div class="ui-block-c">
<span>
#Html.EditorFor(m => m.Mask)
#Html.ValidationMessageFor(m => m.Mask)
</span>
</div>
<div class="ui-block-d">
<span>
#Html.EditorFor(m => m.Id)
#Html.ValidationMessageFor(m => m.Id)
</span>
</div>
</div>
<div data-role="main" class="ui-content">
<div data-role="controlgroup" data-type="horizontal">
<input type="submit" id="addExistingIp" cssclass="ui-btn ui-corner-all ui-shadow" value="Add" />
</div>
</div>
}
ViewModel:
public Contact ContactDetails { get; set; }
[Required]
public bool ExistingAddress { get; set; }
public List<ExistingIp> ExistingIps { get; set; }
[Required]
[DataType(DataType.MultilineText)]
public string ExistingNotes { get; set; }
You can modify the AddExistingIp to just store the data. And to make a RedirectToAction Index. There you will take the data from Session and pass it to the Model.
[HttpPost]
public ActionResult AddExistingIp([Bind(Include = "Subnet, Cidr, Mask")]ExistingIp existingIp)
{
if(Session["pa_ipv4Session"] != null)
{
pa_ipv4 pa_ipv4 = (pa_ipv4)Session["pa_ipv4Session"];
if(pa_ipv4.ExistingIps == null)
{
pa_ipv4.ExistingIps = new List<ExistingIp>();
}
pa_ipv4.ExistingIps.Add(existingIp);
}
else
{
pa_ipv4 pa_ipv4 = new pa_ipv4();
Session["pa_ipv4Session"] = pa_ipv4;
pa_ipv4.ExistingIps = new List<ExistingIp>();
pa_ipv4.ExistingIps.Add(existingIp);
}
return RedirectToAction("Index");
}
The Index Action will look similar with this, where you take data from Session and use it in your Model
public ActionResult Index()
{
var viewModel = new ViewModel();
// take data from Session
pa_ipv4 pa_ipv4 = Session["pa_ipv4Session"] as (pa_ipv4);
// some verification
// add the list from Session to model
viewModel.ExistingIps = pa_ipv4.ExistingIps;
return View(viewModel);
}
Also, I think your Index View you should at ExistingIpView you should pass the Model to display.
#model ViewModel
<div id="ExistingIpList">
#{Html.RenderPartial("ExistingIpView", Model.ExistingIps);}
</div>
<div id="addExisting">
#{Html.RenderPartial("AddExistingIp");}
</div>
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! :)