My partial view is not being set up correctly - c#

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/>

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!

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

Why does Ajax.BeginForm load index again before partialview?

I am using Ajax.BeginForm to update a div with a partialview (loading logs based on the search input in the search fields).
The general idea is to load the Index the first time you log in with default values and then only update the log (partial view) when you search from there on.
The problem - When I debug my program it stops at Index in the controller before loading the partial view - resulting in long loading times.
The question - How can I make the Ajax request only load the partial view?
Code
_LogLayout.cshtml
<div id="log" class="tab">
<h1>Log</h1>
#using (Ajax.BeginForm("LogPartialView", "LogModelsController",
new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "divLogs",
}, new
{
id = "NewTableId"
}))
{
<p>#Html.TextBox("SearchString", null, new { #placeholder = "Message" })</p>
if (Roles.IsUserInRole(WebSecurity.CurrentUserName, "Admin"))
{
<p>
#Html.DropDownList("SelectedCustomer", Model.LogModelVmObject.CustomerList, new { #id = "logdropdownlabel", #class = "dropdownlabels" })
</p>
}
<p>
<input type="submit" class="standardbutton logsearch" name="submit" value="Search" />
</p>
}
#using (Html.BeginForm("ExportData", "LogModels"))
{
<input type="submit" name="export" class="standardbutton export" value="Export to Excel" />
}
<div id="divLogs">
#Html.Raw(ViewBag.Data)
#Html.Partial("_LogPartialLayout")
</div>
</div>
</div>
LogModelsController.cs
/// <returns>
/// Returns the populated log with the current customers information if the user is of the Role Member,
/// otherwise if the user is in the Role Admin - then show all customers logs by default.
/// </returns>
public async Task<ActionResult> Index()
{
if (Session["myID"] == null)
return ExpireSession();
const int pageNumber = 1;
var lmvm = new LogModelVm { CurrentSort = null };
var myId = Convert.ToInt32(Session["myID"].ToString());
if (Roles.IsUserInRole(WebSecurity.CurrentUserName, "Admin"))
{
_customer = _cdvdb.GetAllCustomerIds();
_message = _db.GetLogs();
}
else if (Roles.IsUserInRole(WebSecurity.CurrentUserName, "Member"))
{
_message = _db.GetLogsById(myId);
}
var logs = _message.OrderByDescending(i => i.Timestamp).ToPagedList(pageNumber, PageSize);
if (Roles.IsUserInRole(WebSecurity.CurrentUserName, "Admin"))
{
if (_customer != null)
{
var selectListItems = _customer as SelectListItem[] ?? _customer.ToArray();
foreach (var log in logs)
log.Name = selectListItems.FirstOrDefault(a => a.Value == log.CustomerId.ToString())?.Text;
lmvm.CustomerList = selectListItems;
}
}
lmvm.Logs = logs;
var model = new LogStatisticsModel
{
LogModelObject = new LogModel(),
StatisticsModel = await StatisticsData.GetAllCurrentStatisticsValues(1, DateTime.Now),
LogModelVmObject = lmvm
};
return View(model);
}
/// <returns>
/// Returns a partial view of the log.
/// </returns>
[HttpPost]
public ActionResult LogPartialView(string searchString, int? selectedCustomer, string currentMessageFilter, string currentCustomerFilter, int? page, string sortOrder)
{
// Some code.
return PartialView("_LogPartialLayout", model);
}
RouteConfig.cs
using System.Web.Mvc;
using System.Web.Routing;
namespace MyProject
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Login", action = "Index", id = UrlParameter.Optional });
routes.MapRoute("Log", "{controller}/{action}/{Id}");
routes.MapRoute("Admin", "");
}
}
}
Index.cshtml
#model MyProject.Models.LogStatisticsModel
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
#{
ViewBag.Title = "MyPortal";
Layout = "~/Views/Shared/_LogLayout.cshtml";
}
After a long discussion with #StephenMuecke which (among a ton of useful things) told me to try and comment out every single javascript in the _LogLayout.cshtml file and one by one uncomment them back and see if any of them caused the problem.
I found that the following script caused the problem.
<script type="text/javascript">
$('#loadercheck').click(function ()
{
$('#loader').show();
$.ajax(
{
success: function ()
{
$('#loader').delay(1200).hide(400);
}
});
})
</script>
The following script was used to display a spinning loader while the log was loading data. Apparently this caused the Index() to be called again. So I will have to find a new way to display a loader now...

ASP.NET MVC Partial View issue when Submitting a Form

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());
}

How can I create a search functionality with partial view in asp.net mvc 4

I am using ASP.NET MVC 4 with entity framework model first.
In my "Masterpage.cshtml" I want to have a partial view which contains a textbox and a button.
The search is looking for the items title, if the text contains a items title it should display those items.
When a text is submitted the #renderbody() should show a view with the items.
My question is how can I do this in a good way? whats a good and easy approach?
So far I have done this:
Created a method in my repository that does the search function:
public List<News> Search(string query)
{
var queryz = db.News.Where(x => x.Title.Contains(query));
return queryz.ToList();
}
Now when it comes to my Searchcontroller im kinda lost how to do this. Beacuse one actionresult need to be the partialview that has a string query parameter and other one that contains a view that will display the items?
What I have done right now is having the whole process in same actionresult:
Repository rep = new Repository();
[HttpPost]
public ActionResult Search(string query)
{
var searchlist = rep.Search(query);
var model = new ItemViewModel()
{
NewsList = new List<NewsViewModel>()
};
foreach (var NewsItems in searchlist)
{
FillProductToModel(model, NewsItems);
}
return View(model);
}
private void FillProductToModel(ItemViewModel model, News news)
{
var productViewModel = new NewsViewModel
{
Description = news.Description,
NewsId = news.Id,
Title = news.Title,
link = news.Link,
Imageurl = news.Image,
PubDate = news.Date,
};
model.NewsList.Add(productViewModel);
}
any kind of help is appreciated alot!
You could use the following approach:
Index.cshtml
Have one DIV that calls the search controller action, and another that'll display the results.
<div id="search-form">
#Html.Action("Search", "Home"); // GET action in controller that displays form
</div>
<div id="search-results">
</div>
_SearchFormPartial.cshtml
Create a partial view that'll contain the search form. You can use Ajax.BeginForm so when a user searches the results will be displayed in the search-results DIV in Index.cshtml by AJAX. UpdateTargetId specifies that we want to pass the results of the search to the search-results DIV.
#using (Ajax.BeginForm("Search", "Home", FormMethod.Post,
new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
UpdateTargetId = "search-results"
}))
{
<div>
#Html.TextBox("query")
<input type="submit" value="Search" />
</div>
}
Controller
In your controller you'll need one action to display the form (partial view above) and another to process the search query and retun another partial view that'll display the results:
[HttpGet]
public ActionResult Search()
{
return PartialView("_SearchFormPartial");
}
[HttpPost]
public ActionResult Search(string query)
{
if(query != null)
{
try
{
var searchlist = rep.Search(query);
var model = new ItemViewModel()
{
NewsList = new List<NewsViewModel>()
};
return PartialView("_SearchResultsPartial", model);
}
catch (Exception e)
{
// handle exception
}
}
return PartialView("Error");
}
_SearchResultsPartial.cshtml
This partial will display the results. It's strongly typed taking in an ItemViewModel.
#model Namespace.ViewModels.ItemViewModel
#if (Model.SearchResults.Count == 0)
{
<h3 class="text-error">No items matched your search query!</h3>
}
else
{
foreach (var result in Model.NewsList)
{
// display search results
}
}
If your _SearchResultsPartial.cshtml is not inserted into the DOM element of given ID, you should add a script: query.unobtrusive-ajax.js
It fixed the MattSull's solution in my case

Categories