The way I have structured the form is that there are multiple "Test Connection" submit buttons plus a "Save" submit button to save all the credentials and urls for each test connection. I have seen some suggested solutions but I don't feel like doing an ajax or javascript. So I'm wondering if this is possible. And by the way, I would like to pass values to the controller via the submit buttons as enum values and receive that enum in my controller.
I could easily make multiple ActionResults but it just feels so convoluted for me and if I have to change something in the test connection, I would have to change all. So I would like to have only one ActionResult method for TestConnection plus one Save ActionResult all within the same form.
When I click the Save button, all the credentials are sent to the controller as the ApplicationSettings model.
When I click the Test Connection button, I still receive the ApplicationSettings model plus the DatabaseSystems enum and depending on the enum received form the button, I would do the necessary connection.
Below are the code snippets but I just can't make them work.
Approaches tried:
1. Blank form action, submit buttons has name as "Save" and "TestConnection" accordingly. - Save works. TestConnection does not work saying The resource cannot be found.
2. Form action pointed to "TestConnection", TestConnection button names set as
"database" while value set as #DatabaseSystems.xxx, Save button set as "action:Save", ActionResult method for Save added [MultipleButton(Name = "action", Argument = "Save")] - TestConnection works, Save does not work saying ambiguous request.
I can't seem to figure out the config to make them both work. :(
View
#using Models.Enums
#model MyApp.Data.ApplicationSettings
#Html.AntiForgeryToken()
#using (Html.BeginForm())
{
<div class="row">
<div class="col-md-2">
#Html.EditorFor(model => model.con1_un, new { htmlAttributes = new { #class = "form-control", #placeholder = Html.DisplayNameFor(model => model.con1_un) } })
</div>
<div class="col-md-2">
#Html.EditorFor(model => model.con1_pw, new { htmlAttributes = new { #class = "form-control", #placeholder = Html.DisplayNameFor(model => model.con1_pw) } })
</div>
<div class="col-md-7">
#Html.EditorFor(model => model.con1_url, new { htmlAttributes = new { #class = "form-control", #placeholder = Html.DisplayNameFor(model => model.con1_url), #rows = "1", #style = "max-width:520px !important" } })
</div>
<div class="col-md-1 pull-right">
<button type="submit" class="btn btn-warning pull-right" name="database" value="#DatabaseSystems.System1" data-toggle="collapse" data-target="#loading"><span class="glyphicon glyphicon-link"></span> Test Connection</button>
</div>
</div>
<div class="row">
<div class="col-md-2">
#Html.EditorFor(model => model.con2_un, new { htmlAttributes = new { #class = "form-control", #placeholder = Html.DisplayNameFor(model => model.con2_un) } })
</div>
<div class="col-md-2">
#Html.EditorFor(model => model.con2_pw, new { htmlAttributes = new { #class = "form-control", #placeholder = Html.DisplayNameFor(model => model.con2_pw) } })
</div>
<div class="col-md-7">
#Html.EditorFor(model => model.con2_url, new { htmlAttributes = new { #class = "form-control", #placeholder = Html.DisplayNameFor(model => model.con2_url), #rows = "1", #style = "max-width:520px !important" } })
</div>
<div class="col-md-1 pull-right">
<button type="submit" class="btn btn-warning pull-right" name="database" value="#DatabaseSystems.System2" data-toggle="collapse" data-target="#loading"><span class="glyphicon glyphicon-link"></span> Test Connection</button>
</div>
</div>
<div class="row">
<div class="col-md-2">
#Html.EditorFor(model => model.con3_un, new { htmlAttributes = new { #class = "form-control", #placeholder = Html.DisplayNameFor(model => model.con3_un) } })
</div>
<div class="col-md-2">
#Html.EditorFor(model => model.con3_pw, new { htmlAttributes = new { #class = "form-control", #placeholder = Html.DisplayNameFor(model => model.con3_pw) } })
</div>
<div class="col-md-7">
#Html.EditorFor(model => model.con3_url, new { htmlAttributes = new { #class = "form-control", #placeholder = Html.DisplayNameFor(model => model.con3_url), #rows = "1", #style = "max-width:520px !important" } })
</div>
<div class="col-md-1 pull-right">
<button type="submit" class="btn btn-warning pull-right" name="database" value="#DatabaseSystems.System3" data-toggle="collapse" data-target="#loading"><span class="glyphicon glyphicon-link"></span> Test Connection</button>
</div>
</div>
... and many more test connections for different systems
<button type="submit" class="btn btn-success pull-right" name="Save" data-toggle="collapse" data-target="#loading"><span class="glyphicon glyphicon-floppy-disk"></span> Save</button>
}
Controller
[HttpPost]
ActionResult TestConnection(ApplicationSettings model, DatabaseSystems database)
{
// depending on the DatabaseSystems enum passed, then I'll do the necessary connection check.
{
[HttpPost]
ActionResult Save(ApplicationSettings model)
{
// Save credentials entered in all the input fields above for con1, con2 & con3.
}
Model
[Serializable]
public class ApplicationSettings
{
public string con1_un { get; set; }
public string con1_pw { get; set; }
public string con1_url { get; set; }
public string con2_un { get; set; }
public string con2_pw { get; set; }
public string con2_url { get; set; }
public string con3_un { get; set; }
public string con3_pw { get; set; }
public string con3_url { get; set; }
... and many more systems
}
Enum
public enum DatabaseSystems
{
System1,
System2,
System3,
... and many more systems
}
Use single action name with different parameters for multiple submit button.and give name is same in both button but value is different
for check connectin
<button type="submit" class="btn btn-warning pull-right" name="save" value="#DatabaseSystems.System3" data-toggle="collapse" data-target="#loading"><span class="glyphicon glyphicon-link"></span> Test Connection</button>
for save
<button type="submit" class="btn btn-warning pull-right" name="Save" value="save" data-toggle="collapse" data-target="#loading"><span class="glyphicon glyphicon-link"></span> Save</button>
[HttpPost]
ActionResult Save(ApplicationSettings model,string Save)
{
if(Save=="Testconnection")
{
//do your code on save
}
if(save="Save")
{
//do your code on save
}
}
Finally got it. Though #Stephen Muecke did not really provide a direct solution, I should say he made me reconsider using formaction again so I still have to thank him. Thanks mate! Below is how I solved it:
View
#using Models.Enums
#model MyApp.Data.ApplicationSettings
#Html.AntiForgeryToken()
#using (Html.BeginForm())
{
...
<button type="submit" class="btn btn-warning pull-right" name="database" value="#DatabaseSystems.System1" formaction="Admin/TestConnection" data-toggle="collapse" data-target="#loading"><span class="glyphicon glyphicon-link"></span> Test Connection</button>
...
<button type="submit" class="btn btn-warning pull-right" name="database" value="#DatabaseSystems.System2" formaction="Admin/TestConnection" data-toggle="collapse" data-target="#loading"><span class="glyphicon glyphicon-link"></span> Test Connection</button>
}
Controller
public ActionResult TestConnection(ApplicationSettings model, DatabaseSystems database)
{
// at the end, instead of putting return View() or return("Index", model), I used below code
return Redirect("/[ControllerName]");
{
... this way, formaction will do the calling of the ActionResult method for me while keeping the name attribute of the button free for other purposes such as passing it as a parameter to my TestConnection method.
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 a big problem with MVC Telerik UI for ASP.NET
I am trying to get a checkbox up for a boolean field. I know we have two input fields to return the value false when the box is not touched.
When I do not touch the CBox, I get the value 'false' as expected. When I check the box, I get false too because the CBOx is returning a string = "true,false" which makes it impossible to convert directly to bool.
View
public class role
{
public string role_name { get; set; }
public bool add_school { get; set; }
}
Controller
public ActionResult test()
{
return View();
}
[HttpPost]
public async Task<ActionResult> test(Models.role role)
{
var z = Request["cb_addschool"];
var x = 1;
return RedirectToAction("Index");
}
View
#model Models.role
#using (Html.BeginForm("test", "Home", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h2>Add a New Role</h2>
<hr />
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.role_name, new { #class = "col-md-1 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.role_name, new { #class = "form-control form-control-big" })
</div>
</div>
<div class="form-group">
#Html.Kendo().CheckBoxFor(m=>m.add_school).Name("cb_addschool").Label("Add School")
</div>
<div class="form-group">
<div class="col-md-offset-3 col-md-9">
<input type="submit" class="btn btn-login" value="Register" />
</div>
</div>
}
Please, any help?
Remove this code from your action method:
var z = Request["cb_addschool"];
You have this value inside your role model. So this is pointless in this case.
Than remove this attribute from Kendo CheckBoxFor:
.Name("cb_addschool")
You don't have to need that (the property will be bound correctly without that).
Small hint: if you are using Kendo - use the Kendo().TextBoxFor method instead of #Html.TextBoxFor (or add "k-textbox" class to your TextBoxFor - it will use Kendo CSS styles).
Here is an example:
#(Html.Kendo().TextBoxFor(model => model.role_name)
.HtmlAttributes(new { placeholder = "Select role", #class = "form-control form-control-big" })
)
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.
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");
}