Create reusable form contact component in asp.net mvc - asp.net-mvc

I'm newbie at asp.net mvc, I'm trying to develop a reusable contact form component for asp.net mvc .
I have tryed to do it creating a PartialView with a form, I don't know if this is the better approach, for create a reusable component
My PartialView is
#model MyModel.ContactData
#using (Html.BeginForm("ContactForm", "ContactForm", FormMethod.Post)) {
<fieldset>
<p>
#Html.LabelFor(model => model.MailAddress)
#Html.EditorFor(model => model.MailAddress)
</p>
<p>
#Html.LabelFor(model => model.Message)
#Html.TextAreaFor(model => model.Message)
</p>
<input type="submit" value="Save" />
</fieldset>
}
The problems start with the controller, the controller is a specific controller for only this partialView.
public class ContactFormController : Controller
{
[HttpPost]
public ActionResult ContactForm(ContactData contactData)
{
if (ModelState.IsValid)
{
return PartialView("MessageSend");
}
return PartialView();
}
}
My problem is in case of some of the required fields are empty, in that case the controller returns only the partial view, not returning the partival view inside its parent context. I have tryed calling the PartialView from parent View as #Html.Partial, #Html.RenderAction, #Html.RenderPartial and the same occurs.
How can I return the partial view Inside it's parent Context? I have tried with
return View(ParentViewsName, contactData) but I dislike it because on form submitting it changes the url on address bar from /Contact to /ContactForm/ContactForm.
Perphaps I'm trying to create a reusable component with a wrong approach? It's better to update with ajax only the PartialView? Alternatives?
Thanks

From my understanding, you wish to display status message which is a partial view after user successfully submits the form. I think tempdata will be apt for this kind of situation.
public class ContactFormController : Controller
{
[HttpPost]
public ActionResult ContactForm(ContactData contactData)
{
if (ModelState.IsValid)
{
TempData["success"] = true;
return RedirectToAction("parentpage");
}
return View(contactData);
}
}
In parent page, check whether TempData["success"] is null and display the partial view "MessageSend".

Finally as Sundeep explains I have done this with ajax like this example Partial ASP.NET MVC View submit.
Thanks for your help.

Related

MVC5 How to do a post from partialview?

My partialview:
#model Alina_2017.Models.DropDownModel
<h2>Groepen</h2>
<div>
<div>
#using (Html.BeginForm("SelectGroup", "~/Controllers/WerkvormController"))
{
#Html.DropDownListFor(x => x.selectedItem, new SelectList(ViewBag.groepen, "id", "Naam"), "Select", new { #class = "form-control" })
<input type="submit" id="zoekgroep" value="Zoeken" />
}
</div>
</div>
My main view:
#model Alina_2017.Models.WerkvormModel
#{
ViewBag.Title = "Index";
}
#Html.Partial("~/Views/DropDown/Groepen.cshtml")
//More irrelevant html
My controller:
public ActionResult Index()
{
ViewBag.groep1 = convertWerkvorm(db.Werkvormens.Where(f => f.GroepenWerkvormID == 1).ToList());
ViewBag.groep2 = convertWerkvorm(db.Werkvormens.Where(f => f.GroepenWerkvormID == 2).ToList());
ViewBag.groep3 = convertWerkvorm(db.Werkvormens.Where(f => f.GroepenWerkvormID == 3).ToList());
setViewBags();
return View();
}
[HttpPost]
public ActionResult SelectGroup(DropDownModel model)
{
// the value is received in the controller.
var selectedItem = model.selectedItem;
Debug.WriteLine(selectedItem);
return View("Index");
}
I'm getting a HTTP Error 404.0 - Not Found. Is it possible to call an action from a different controller? The reason it's in a partial view is because I'm using two different models + I'll be using the partialview in multiple other views (at least once I get it to work).
Your controller's name is wrong.
Replace
#using (Html.BeginForm("SelectGroup", "~/Controllers/WerkvormController"))
with
#using (Html.BeginForm("SelectGroup", "Werkvorm"))
You can verify the actual post URL if you view your source in browser, or check network tab in the browser's development tools.
The second argument to the BeginForm() method is simply the name of the controller, not its file:
#using (Html.BeginForm("SelectGroup", "Werkvorm"))
{
}
You can post to any server-side action from anywhere. There's no limit based on how the view is rendered because once everything is rendered it's all just client-side markup no matter where it came from.
As a learning exercise, examine the actual rendered markup in your browser's debugging tools and see the URLs created for the forms. Regardless of how the partial views are arranged, which controller returned the view, what the models are, etc... It's all just HTML in the end. You can even manually write a simple .html file with a form on it which successfully posts to a server-side ASP.NET MVC action.

HTTPPOST in MVC not returning view

A simple action method when called with httppost attribute not returning view.but with post perfectly working. Just 2 days back I started learning MVC. For learning purpose I made a simple action to return a view with httppost but it dint work. i searched in forums too but dint get clear idea.. can anybody explain..
[HttpPost]
public ActionResult login(LoginModel loginmodel)
{
if (ModelState.IsValid)
{
}
return View();
}
My view:
<h2>login</h2>
#using (Html.BeginForm())
{
<div class="editor-label">
#Html.LabelFor(model => model.username)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.username)
#Html.ValidationMessageFor(model => model.username)
</div>
<input type="submit" value="Login" />
}
You need to return the viewmodel back to the view.
[HttpPost]
public ActionResult login(LoginModel loginmodel)
{
if (ModelState.IsValid)
{
// to do : check login and redirect
}
// validation failed. let's return to the view.
return View(loginmodel);
}
From the comments from #Shyju's answer you state that you are receiving a 404 error message when you submit the form. This indicates to me that the form's action doesn't have the correct URL. This isn't too surprising as the ASP.NET MVC framework is picking the URL based on some assumptions.
Change the the from declaration in your view to explicitly defined the action name and controller name of your HttpPost login action.
#using (Html.BeginForm("login", "MyControl"))
Replace "MyControl" with the actually name of your controller.
You should define your Controller and Action name in Form like
#using (Html.BeginForm("Action", "Controller"))
And then you need to return the Model in view like
return view(model)
Hope it will help you.

Best practice for rendering data after posting a form in mvc 4.0

Example:
I have a 'Contact Us' view and controller.
My view renders a contact us form as well as the rest of the page containing postal, telephone and email information.
When the form is submitted I want to render the same data, just minus the contact us form and display a 'message sent' instead.
I have a 'Send' method on the controller and can create a 'Send' view with all the data from the contact us view, minus the contact us form and with the 'message sent' string. But obviously having the code now duplicated in two places is far from ideal.
Is there a better way to do this?
I would suggest you to use Ajax.BeginForm instead of using BeginForm. The reason is you don't need to create another action, Ajax.BeginForm will update the display partial view for you.
Below is an example:
Action
[HttpGet]
public ActionResult Contact()
{
return View(new Contact());
}
[HttpPost]
public ActionResult Contact(Contact contact)
{
if (ModelState.IsValid)
{
//
}
return PartialView("_messagePartialView", contact);
}
View
#model Demo.Models.Contact
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
<div id="result">
#using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "result" }))
{
#Html.EditorFor(x => x.Email)
<input type="submit" value="OK" />
}
</div>
Partial View: _messagePartialView
#model Demo.Models.Contact
<h1>
#Model.Email
</h1>
I will assume you have a Contact Model that you use to get the data from user.
And I assume you have the Send Method as follows:
[HttpPost]
public ActionResult Send(Contact contact){
// process your model. ie : send email etc.
TempData["contactData"] = contact;
return RedirectToAction("Sent");
}
public Actionresult Sent(){
return View();
}
In sent view you can use TempData and access Contact model properties.

MVC Parent Child actions page rendering?

I am learning to embed a child action inside a parent action, and render the whole page properly when a form is submitted from the child action.
ParentAction.cshtml--------------------------------------
#model Web1.Models.ParentActionModel
#{ViewBag.Title = "ParentAction";}
<h2>Parent Action</h2>
#Html.ValidationSummary(true, "Please correct parent errors and try again.")
#using (Html.BeginForm()) {
//parent forminput stuff
<input type="submit" value="Parent Button" />
}
#Html.Action("ChildAction","Home") <!-- ChildAction is included here -->
ChildAction.cshtml (included in parent.cshtml) ------------
#model Web1.Models.ChildActionModel
#{ViewBag.Title = "ChildAction";}
<h2>Child Action</h2>
#Html.ValidationSummary(true, "Please correct child errors and try again.")
#using (Html.BeginForm("ChildAction", "Home")) {
//child form input stuff
<input type="submit" value="Child Button" />
}
HomeController.cs-----------------------
public ActionResult ParentAction() {
return View();
}
[HttpPost]
public ActionResult ParentAction(ParentActionModel pmodel) {
//do model update stuff
return View(pmodel);
}
[ChildActionOnly]
public ActionResult ChildAction() {
return PartialView();
}
[HttpPost]
public ActionResult ChildAction(ChildActionModel cmodel) {
//do model update stuff
return PartialView(cmodel); // <---This is wrong, What's the correct way to do it?
}
Now, when I click the "Child Button", I will only get the view of the child action (durrr!), how do I fix it to generate full page parent+children view? It seems like a logic easy enough, but I am stuck on it for hours.
So, if I removed the [ChildActionOnly] in HttpPost Details method,
when I click submit, only the Details.cshtml partialView is returned,
not with the Master.cshtml, which is not what I want, neither.
That's because you should not return a PartialView in this case, but a full View:
[HttpPost]
public virtual ActionResult Details(DetailsModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
return RedirectToAction("Success");
}
You might also need to only conditionally render the Details action to avoid infinite loops:
#if (!IsPost)
{
#Html.Action("Details", "Home")
}
Obviously if you want to preserve the original context you were in when you invoked this POST action, you will have to use AJAX and then invoke this POST action with AJAX and replace only the corresponding part of the DOM.

Getting posted values in MVC PartialView

I've created a PartialView which I render with Html.RenderPartial, passing the name of the view and the strongly-typed data item to bind to (below):
<% Html.RenderPartial("SearchViewUserControl", ViewData["SearchData"]); %>
The partial view has a form containing a submit button:
<% using (Html.BeginForm("Search", "Home"))
{ %>
...
<div>
<input type="submit" value="Search" />
</div>
<% } %>
I've set a breakpoint in my controller's action method (below) but nothing is set in searchData. What am I doing wrong?
public ActionResult Search(SearchDomain searchData)
{
if (ModelState.IsValid)
{
}
return View();
}
You need to post the actual form elements for anybody to know whats wrong.
The form html is what sets the binding to SearchDomain. You want to have your form elements named like this:
<input name="searchData.SomeProperty">
For them to bind to your action parameter.
In order to pull a SearchDomain object out of your view from a controller method, your view has to either inherit from System.Web.Mvc.ViewPage<Models.SearchDomain>, or a custom ViewModel class that contains a SearchDomain object.
The other way to do it is to have your view inherit from System.Web.Mvc.ViewPage, and use UpdateModel to cast the view data to a SearchDomain object. Something like this:
public ActionResult Save()
{
SearchDomain domain = new SearchDomain ();
UpdateModel(domain , new[] { "Name", "Email", "Phone", ... });
return View(domain);
}
To be honest, I think RenderAction is much easier to use.

Resources