ASP.NET MVC Partial View issue when Submitting a Form - c#

I am trying to display a Partial View inside a master (Index) View:
Steps:
User selects a Dropdown item from the Index View.
This displays a Partial View that has a search Form.
User fills the search Form and then clicks the Submit button.
If the search Form is valid, a new page (Results View) is displayed.
Else, the search Form Partial View should be re displayed with errors INSIDE the master View
I'm having a problem with number 4 because when the search Form submits, it only displays the partial View in a new window. I want to display the whole page : Index View + Partial View with errors.
Suggestions? This is what I have:
Image
Controller
public class AppController : Controller
{
public ActionResult Index()
{
return View(new AppModel());
}
public ActionResult Form(string type)
{
if (type == "IOS")
return PartialView("_IOSApp", new AppModel());
else
return PartialView("_AndroidApp", new AppModel());
}
public ActionResult Search(AppModel appModel)
{
if (ModelState.IsValid)
{
return View("Result");
}
else // This is where I need help
{
if (appModel.Platform == "IOS")
return PartialView("_IOSApp", appModel);
else
return PartialView("_AndroidApp", appModel);
}
}
}
Model
public class AppModel
{
public string Platform { get; set; }
[Required]
public string IOSAppName { get; set; }
[Required]
public string AndroidAppName { get; set; }
public List<SelectListItem> Options { get; set; }
public AppModel()
{
Initialize();
}
public void Initialize()
{
Options = new List<SelectListItem>();
Options.Add(new SelectListItem { Text = "IOS", Value = "I" });
Options.Add(new SelectListItem { Text = "Android", Value = "A"});
}
}
Index.cshtml
#{ ViewBag.Title = "App Selection"; }
<h2>App Selection</h2>
#Html.Label("Select Type:")
#Html.DropDownListFor(x => x.Platform, Model.Options)
<div id="AppForm"></div> // This is where the Partial View goes
_IOSApp.cshtml
#using (Html.BeginForm("Search", "App"))
{
#Html.Label("App Name:")
#Html.TextBoxFor(x => x.IOSAppName)
<input id="btnIOS" type="submit" value="Search IOS App" />
}
AppSearch.js
$(document).ready(function () {
$("#Platform").change(function () {
value = $("#Platform :selected").text();
$.ajax({
url: "/App/Form",
data: { "type": value },
success: function (data) {
$("#AppForm").html(data);
}
})
});
});

You need to call the search method by ajax too.
Change the index.html and then
1- if Form is valid replace the whole html or the mainContainer( The div that i have added to view).
2- else just replace the partial view.
#{ ViewBag.Title = "App Selection"; }
<div id="mainContainer">
<h2>App Selection</h2>
#Html.Label("Select Type:")
#Html.DropDownListFor(x => x.Platform, Model.Options)
<div id="AppForm"></div> // This is where the Partial View goes
</div>
Remove the form tag from your partial view just call an ajax call method for searching.
May be easiest way to handle this problem is using MVC unobtrusive ajax.

I would say use inline Ajax to submit this form.
#using (Html.BeginForm("Search", "App"))
{
#Html.Label("App Name:")
#Html.TextBoxFor(x => x.IOSAppName)
<input id="btnIOS" type="submit" value="Search IOS App" />
}
change upper given code into following code
#using (
Ajax.BeginForm(
"Form", "App",
new AjaxOptions()
{
UpdateTargetId = "App",
HttpMethod = "Post"
}
)
)
{
<div class="editor-label">
#Html.Label("App Name:")
</div>
<div class="editor-field">
#Html.TextBoxFor(x => x.IOSAppName)
</div>
<input id="btnIOS" type="submit" value="Search IOS App" />
}
//in controller change the parameter of the given method from string type to model object which will be posted by ajax form.
public ActionResult Form(AppModel appModel)
{
if (appModel.type == "IOS")
return PartialView("_IOSApp", new AppModel());
else
return PartialView("_AndroidApp", new AppModel());
}

Related

Unable to get partial view to change dynamically in MVC

Somewhat new to web apps here, and struggling to get this to work. Would appreciate any input.
Essentially, I have a main (Create) view with a dropdown and a partial view. Based on the selected value, the partial view needs to change, i.e. I want to render different .cshtml's. I've gone through many other similar sounding questions and tried various combinations without success.
The most promising one I found was this: https://www.c-sharpcorner.com/UploadFile/ansh06031982/passing-data-using-viewdata-viewbag-tempdata-session-vari/ but it still doesn't get me what I need. Nothing changes on my View, i.e the partial view does not render even though the debug shows the right values being passed.
Model:
public class myModelType
{
[Key]
public int ID { get; set; }
[Required]
public string modelType { get; set; }
public string Input1
public string Input2
}
Controller
public class myModelTypeController : Controller
{
public ActionResult Create()
{
myModelType myModel = new myModelType();
return View(myModel);
}
}
public ActionResult myModelTypeChange(FormCollection form)
{
String typeSelected = form[“modelTypeDDL”];
TempData[“modelTypeSelected”] = typeSelected;
Return RedirectToAction(“myPartialView”);
}
public ActionResult myPartialView()
{
myModelType myModel = new myModelType();
string typeSelected = TempData[“modelTypeSelected”];
string partialViewForm = “”;
If (typeSelected == “type 1”)
partialViewForm = “form1”;
else
partialViewForm = “form 2”
return PartialView(partialViewForm, myModel);
}
Main (Create) View
#model myModelType
<script src = “#Url.Content(“~/Scripts/jquery-3.4.1.min.js”)”></script>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
//bunch of html controls
#Html.DropDownList(“Model Type”, Enumerable.Empty<SelectListItem>,”- - - “, new { #class = “form-control”, id = “modelTypeDDL})
//Need to load partial view here
<div class = “container” id= “partialViewPlaceHolder”>
</div>
}
#section Scripts {
#Scripts.Rended(“~/bundles/jqueryval”)
}
Partial view 1 (form1.cshtml)
#model myModelType
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
//html specific to form1
#Html.EditorFor(“model=>model.Input1”, new { #class = “form-control”})
}
Partial view 2 (form2.chstml)
#model myModelType
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
//html specific to form2
#Html.EditorFor(“model=>model.Input2”, new { #class = “form-control”})
}
jquery script
<script language =”JavaScript” type=”text/javascript”>
$(document).ready(function() {
$(“#modelType”).change(function() {
$.post(“/myModelTypeController/myModelTypeChange”, {modelType: $(this).val(), function(data){
$(“partialViewPlaceHolder”).load(data);
});
});
});
</script>
The partial view files form1 and form2 are in the same folder as the main Create view.
Would appreciate any help in getting this to work, or any other suggestions on how to get a partial view to switch files based on DDL input. Thanks!

My partial view is not being set up correctly

I have an application done in ASP.NET MVC and I am having an issue where my partial view is not being rendered after my form is submitted. What it does is that it reloads the entire page.
Here is my Model:
using System.Collections.Generic;
namespace Portfolio.Models
{
public class HomeViewModel
{
public List<User> User = new List<User>();
}
}
Here is my View:
#{
ViewBag.Title = "Home Page";
}
#model Portfolio.Models.HomeViewModel
#using (Ajax.BeginForm("FooForm",
new AjaxOptions
{
HttpMethod = "get",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "FooView"
}))
{
<button type:"submit" value:"Refresh/>
}
#Html.Partial("_FooView", Model)
<script>
window.onload = function () {
window.setTimeout(function () { $("#FooForm").submit(); }, 5000);
};
</script>
Here is my partial view:
#model Portfolio.Models.HomeViewModel
<div id="FooView">
#for (int i = 0; i < Model.User.Count; i++)
{
<form>
<div id="Name">#Model.User[i].Name</div>
<div id="Email">#Model.User[i].Email</div>
<div id="Date">#Model.User[i].Date</div>
</form>
<div>---------------------
</div>
}
</div>
Finally, here is my Controller:
using Portfolio.Models;
using System;
using System.Timers;
using System.Web.Mvc;
namespace Portfolio.Controllers
{
public class HomeController : Controller
{
public HomeViewModel model = new HomeViewModel();
Timer Timer = new Timer();
public ActionResult Index()
{
ModelState.Clear();
model.User.Add(new User() { Name = "A", Email = "a#email.com", Date = DateTime.Now.AddHours(-1) });
model.User.Add(new User() { Name = "B", Email = "b#email.com", Date = DateTime.Now.AddHours(-2) });
model.User.Add(new User() { Name = "C", Email = "c#email.com", Date = DateTime.Now.AddHours(-3) });
if (Request.IsAjaxRequest())
{
return PartialView("_FooView", model);
}
return View(model)
}
}
}
Can someone see why my Index Action is return the entire view and not the partial view upon Ajax request? Am I not setting my Ajax form properly? Many thanks in advance.
There are a few issues with your code.
First, your script does not submit your form because your form does not have an id attribute with a value of FooForm. Your Ajax.BeginForm() code does not add an id attribute (and is in fact calling a method in your controller named FooForm(). Assuming you really want to call the Index() method in your script then change the BeginForm code to
#using (Ajax.BeginForm("Index", null, new AjaxOptions(....), new { id = "FooForm" }))
which will generate <form .... id="FooForm" >
Then if your actually not hitting the code in the if (Request.IsAjaxRequest()) that returns the PartialView, it means your making a normal submit which means that you have not included jquery.unobtrusive-ajax.js in the view (or its not loading correctly or is loaded in the wrong order)
There is a missing double-quote on this line after Refresh: <button type:"submit" value:"Refresh/>

MVC Ajax Partial View call returns partialview site without "parent"

i worked on a partial reload page via Ajax.
This is what i have:
Controller:
public class EmailController : Controller
{
//
// GET: /Email/
[Authorize]
public ActionResult Index(string id)
{
//.. Some Code here to get my Email List
return View(emails);
}
[Authorize]
public PartialViewResult EmailPartial(string id = "1,2")
{
//.. Some Code here to get my Email List with the new filter
return PartialViewResult(emails);
}
}
Main View:
#model IEnumerable<namespace.Emailgesendetview>
#{
ViewBag.Title = "Index";
AjaxOptions ajaxOpts = new AjaxOptions
{
UpdateTargetId = "emailBody"
};
Layout = "~/Views/Shared/_Default.cshtml";
}
// .... uninteresting html code
<div id="emailBody">
#Html.Action("EmailPartial", new { selectedRole = Model })
</div>
// .... uninteresting html code
// Here comes my action link:
<li>
#Ajax.ActionLink("martin",
"EmailPartial",
"Email",
new { id = "3"},
new AjaxOptions()
{
HttpMethod = "GET",
AllowCache = false,
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "emailBody"
})
</li>
Partial View:
#model IEnumerable<namespace.Emailgesendetview>
<div class="mail-body">
<ul class="mail-list">
#{
foreach (var userMail in Model)
{
//... Code vor showing the models
}
}
</ul>
</div>
If i click on the link now, he starts the function: EmailPartial, but he didn't add (or replace i tryed both) the content. He Opens the EmailPartial view alone?!
In this post:
How to render partial view in MVC5 via ajax call to a controller and return HTML
the Partial function is not a PartialViewResult it's a ActionResult, but i already tryd that.
Would be great i you could show me my error or misstake.
Thanks a lot and have a nice day :)
Because you have not included jquery-unobtrusive-ajax.js in your view or layout so its making a normal redirect. – Stephen Muecke Mar 31 at 10:30

MVC - how to get ListBox selected item's value in Controller?

I have an app which has two listboxes:
#using (Html.BeginForm())
{
#Html.ListBoxFor(m => m.SelectedAttributes, Model.Attributes, new {id="listBoxAvail", SIZE = 5} )
<button type="button" id="add">MoveRight</button>
<button type="button" id="remove">"MoveLeft"></button>
<button type="button" id="remove-all">RemAll</button>
<button type="button" id="select-all">SelAll</button>
<button type="button" id="up" onclick="MoveUp()">Up</button>
<button type="button" id="down" onclick="MoveDown()">Down</button>
#Html.ListBoxFor(m => m.SelectedAttributes2, Model.SelectedItems, new { id = "listBoxSel", SIZE = 5})
<br />
<p>Item Caption Text (140 Characters. HTML not allowed.)</p>
#Html.TextAreaFor(m => m.ItemCaptionText)
<input type="submit" id="submit" value="Save"/>
}
I transfer the selected values from one listbox to the other using jQuery but I append an "L" to the value for later use:
$("#add").click(function () {
$("#listBoxAvail > option:selected").each(function () {
$(this).remove();
val = $(this).val();
temp = $(this);
temp.val('L' + val)
$(temp).appendTo("#listBoxSel");
});
});
I see the Text and Value after I transfer to the right hand listbox with the F12 Developer Tools. What I would to know is how to get that value from C# code in the Controller?
[HttpPost]
public ActionResult Index(OptInViewModel viewModel)
{
AttributeEntities db = new AttributeEntities();
IEnumerable<string> items = viewModel.SelectedAttributes2;
foreach (var item in items)
{
var temp = item;
// Save it
SelectedHarmonyAttribute attribute = new SelectedHarmonyAttribute();
attribute.CustomLabel = viewModel.ItemCaptionText;
//attribute.IsVisible = ?
//attribute.OrderNumber = ?
//attribute.HarmonyAttribute_ID
}
return View("Index");
}
The ViewModel is:
public class OptInViewModel
{
public IEnumerable<string> SelectedAttributes { get; set; }
public IEnumerable<string> SelectedAttributes2 { get; set; }
public IEnumerable<SelectListItem> Attributes { get; set; }
public IEnumerable<SelectListItem> SelectedItems { get; set; }
public string ItemCaptionText { get; set; }
}
I don't fully understand your question, but from what I gather you're trying to pass a parameter to a function call in MVC. Parameters can be added to URLs much like in PHP.
For example a function could be defined as
void Function (string value);
and the URL to call it would be
~/Controller/Function?value=HelloWorld
You can also set up routing. See this answer on StackOverflow for more information:
ASP.NET MVC - passing parameters to the controller
Edit: I see you're trying to use Form submission
Make sure you correctly format your view, not forgetting :
#model Path.To.Model
and controller information:
using (#Html.BeginForm("myMethod", "Controller", FormMethod.Post))

not able to see the view after postback

Hi I have got a drop downlist that I am binding that one in controller I have got one button in view with that I am doing some validations that's working fine,
when I submit the button for validation check i am not able to get the view with error message. Instead of this I am getting error like this " The view 'PostValues' or its master was not found or no view engine supports the searched locations".
would any one help on why I am not able to get the view
here the view is strongly Typed view
and this is my code in controller.
public class CrossFieldsTxtboxesController : Controller
{
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index()
{
var model = NewMethod();
return View(model);
}
private static CrossFieldValidation NewMethod()
{
var model = new CrossFieldValidation
{
SelectedValue = "Amount",
Items = new[]
{
new SelectListItem { Value = "Amount", Text = "Amount" },
new SelectListItem { Value = "Pound", Text = "Pound" },
new SelectListItem { Value = "Percent", Text = "Percent" },
}
};
return model;
}
[HttpPost]
public ActionResult PostValues(CrossFieldValidation model1)
{
model1 = NewMethod();
if (!ModelState.IsValid)
{
return View(model1);
}
else
{
return RedirectToAction("Index");
}
}
}
and this is my view
#model MvcSampleApplication.Models.CrossFieldValidation
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm("PostValues", "CrossFieldsTxtboxes"))
{
#Html.ValidationSummary(true)
<div class ="editor-field">
#Html.TextBoxFor(m => m.TxtCrossField)
#Html.ValidationMessageFor(m=>m.TxtCrossField)
</div>
#Html.DropDownListFor(m=> m.SelectedValue , Model.Items)
<input id="PostValues" type="Submit" value="PostValues" />
}
would any one pls help on this...
This line
return View(model1);
looks for the view named exactly like the action in which it was called. Calling this line from PostValues action assumes there is a view PostValues.cshtml (which apparently does not exist). If you still want to use view Index - you should specify this explicitly:
if (!ModelState.IsValid)
{
return View("Index", model1);
}
As Andrei said. Alternatively, you can give your PostValues method an additional tag:
[HttpPost, ActionName("Index")]
public ActionResult PostValues(CrossFieldValidation model1)
{
if (!ModelState.IsValid)
{
return View(model1);
}
}

Categories