Ajax MVC partialView - c#

I've run into a problem with rendering a partialView in my web application.
What I'm trying to do is using a #Ajax.ActionLink() to fill a div when a button/link is pressed with the content of another view. The issue I'm meeting is that instead of filling the div it reloads the content into a new page, rather than filling the div. All the other answers I've looked up says the same and my syntax is pretty much the same. Is there something in between I've missed or that I should've know before I started attempting this?
Here's my actionlink
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar">Hei</span>
<span class="icon-bar">På</span>
<span class="icon-bar">Deg</span>
</button>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
</ul>
</div>
<div>
#Ajax.ActionLink("Last inn partial view", "_LoadView", new AjaxOptions { InsertionMode = InsertionMode.Replace, HttpMethod = "get", UpdateTargetId="result"})
</div>
</div>
</div>
<div class="container body-content">
#RenderBody()
<hr />
<footer>
<p>© #DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
#Scripts.Render("~/bundles/ajax");
Here's the div I want to fill in
<div class="content">
<div class="content background">
<div id="result">Her står det masse text</div>
</div>
</div>
</div>
Here's the controller
[HttpGet]
public PartialViewResult _LoadView()
{
return PartialView();
}
EDIT:
Forgot to mention that I've got a BundleConfig.cs set up and I've made sure it works as I'm rendering my css through it, though this is the first script I've tried.
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include("~/scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include("~/scripts/jquery.validate*"));
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include("~/scripts/modernizr-*"));
bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include("~/scripts/bootstrap.js"));
bundles.Add(new ScriptBundle("~/bundles/ajax").Include("~/scripts/jquery.unobtrusive-ajax.js", "~/scripts/jquery.unobtrusive-ajax.min.js"));
bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/bootstrap.css", "~/Content/bootstrap-theme.css", "~/Content/bankstyle.css"));
}
}
EDIT: added some text to the question to make it clearer, bolded it out to make it clear. I'm very much open to alternative solutions
EDIT: Realized what I was really looking for was the modal framework in bootstrap. Thanks for the suggestions

Please run this in console:
PM> Install-Package Microsoft.jQuery.Unobtrusive.Ajax -Version 3.2.2
For install please follow next steps: https://www.nuget.org/packages/Microsoft.jQuery.Unobtrusive.Ajax/
Then you must use script file which is located in Scripts folder

Install the Unobtrusive js file:
Run in nuget: Install-Package Microsoft.jQuery.Unobtrusive.Ajax
Add this to your view:
#Scripts.Render("~/Scripts/jquery.unobtrusive-ajax.min.js")

This is not the the answer to the original question but an alternative soloution:
using html.action
<div id="contentContainer">
#Html.Action("Action", "Controller")
</div>
This will call an action and render the view that you return from the action.

Found out what I was really looking for was the modal framework in bootstrap. Fixed my issues in 5 minutes.

Related

Cyclic update of a container in ASP.NET Core MVC

I'm trying to create a cyclic updating container in ASP.NET Core MVC. That's how it look like
And here is the source code:
AdminLTE
For the example in the image, if from database, here are 151 New Orders, when this part of panel is auto-updating, the value will be 151.
One solution for me was to auto-update the whole page, but it's not ok.
Second solution was to use Ajax to call the Index Controller, where I update the model's value from database each time controller is called. But this does not working, because to figure it out, the page must be refreshed. Not ok.
<script type="text/javascript">
function updateModelData() {
setInterval(updateModel, 3000);
var i = 0;
function updateModel() {
$.ajax({
url: "/Home/Index",
type: "GET",
dataType: "json",
success: function (response) {
if (response.data.length == 0) {
// EMPTY
} else {
var obj = jQuery.parseJSON(response.data);
console.log(obj);
}
}
});
}
}
updateModelData();
</script>
So how can I make this informative section to get updated in an automatic cyclic mode?
<section class="content">
<!-- Small boxes (Stat box) -->
<div class="row">
<div class="col-lg-3 col-xs-6">
<!-- small box -->
<div class="small-box bg-aqua">
<div class="inner">
<h3>#Model.doctors_count</h3>
<p>Doctors</p>
</div>
<div class="icon">
<i class="fa fa-users"></i>
</div>
More info <i class="fa fa-arrow-circle-right"></i>
</div>
</div>
<!-- ./col -->
<div class="col-lg-3 col-xs-6">
<!-- small box -->
<div class="small-box bg-green">
<div class="inner">
<h3>#Model.nurses_count<sup style="font-size: 20px"></sup></h3>
<p>Nurses</p>
</div>
<div class="icon">
<i class="fa fa-users"></i>
</div>
More info <i class="fa fa-arrow-circle-right"></i>
</div>
</div>
<!-- ./col -->
<div class="col-lg-3 col-xs-6">
<!-- small box -->
<div class="small-box bg-yellow">
<div class="inner">
<h3>#Model.patients_count</h3>
<p>Patients</p>
</div>
<div class="icon">
<i class="ion ion-person"></i>
</div>
More info <i class="fa fa-arrow-circle-right"></i>
</div>
</div>
<!-- ./col -->
<div class="col-lg-3 col-xs-6">
<!-- small box -->
<div class="small-box bg-red">
<div class="inner">
<h3>65</h3>
<p>This Month</p>
</div>
<div class="icon">
<i class="ion ion-pie-graph"></i>
</div>
More info <i class="fa fa-arrow-circle-right"></i>
</div>
</div>
<!-- ./col -->
</div>
<!-- /.row -->
One option is to use JavaScript function setInterval() and make an update per each desired time interval. See here for details and basic example: JavaScript setInterval
On each time interval trigger an ajax call to a separate method in your controller that returns a partialview (so just the html code you want to update) and append it to your page (make sure you first empty the target container):
example 1: JavaScript append html
example 2 (partialview/ajax update): Update with partial view
For the example in the image, if from database, here are 151 New Orders, when this part of panel is auto-updating, the value will be 151.
To achieve the requirement of updating particular content automatically based on the latest data from database, you can try:
If you'd like to make request to backend using Ajax etc to get data and update the DOM with retrieved data automatically, as #TheMixy mentioned, you can try to call your function repeatedly using setInterval() method.
Besides, you can try to integrate ASP.NET Core SignalR in your project, which could help implement real-time web functionality that enables server-side code to push content to clients instantly.
You can call client methods to push data from server to all connected clients while you add/update orders from your backend code, then update the content on client side once it received the data.

Bootstrap classes are not working with HTML Controls in the view

In my MVC project I applied bootstrap classes to the html input controls but it is not working, before that I used html helper #Html.Editorfor but experiencing the same issue. My code:
HTML:
<div class="container">
<div class="row">
<form action="~/EditProfile/PersonalEdit" method="post" enctype="multipart/form-data">
<div class="col-lg-12 col-md-12 col-sm-12 form-group">
<input type="text" id="fname" name="fname" placeholder="First Name" class="form-control" />
</div>
</div>
</form>
</div>
HTML helper:
#Html.EditorFor(model=>model.FirstName,new {#class="form-control"})
How can I apply Bootstrap classes and make it responsive?
double check and make sure you are linking to bootstrap properly.
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
View the source of this page and check if bootstrap.css is available on the page. Also check in chrome developer tools network tab for the path to css and js files. I should not be returning 404 error.

PartialView not rendering properly on ajax reload

Im having an issue to reload a partial view using ajax.
I have my country form in a partial view, and initially when i load the main page everything is rendered properly.
As demonstrated in the image below, I can search for country using my autocomplete and i can select a countryfrom my combobox (both are kendo-mvc controntrols)
The issue emerges when i select a from my autocomplete and try to load the info of the selected country via ajax. The form is reloaded, the info is displayed but the controls are not being rendered properly. The autocomplete stops working and the combobox is rendered as a normal textbox, displaying the CountryID instead of the Country name.
Code in my view
#using (Html.BeginForm("Index", "CountryManagement", FormMethod.Post, new { id = "country-form" }))
{
#Html.ValidationSummary(true);
<div id="form-content">
#Html.Partial("_CountryForm", Model)
</div>
}
Code in my partialview
<div class="form-group">
#Html.Label("Search Country", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-3">
#(Html.Kendo().AutoCompleteFor(m => m.Search)
.DataTextField("Designation")
//.DataValueField("CountryID")
.Filter("contains")
.MinLength(2)
.DataSource(d => { d.Read(r => r.Action("SearchCountry", "Common")); })
.Events(e => e.Change("onChange")).Deferred()
)
</div>
</div>
Code in my controller
[HttpPost]
public PartialViewResult Edit(int id)
{
//HTTP GET: api/Country/CountryDetails?id={id}&lang={lang}
dynamic model = //code to get selcted country data
return PartialView("_CountryForm", model);
}
Code in my .js file
function onChange() {
if ($("#Search").data("handler")) {
var data = $("#Search").data("handler").dataSource.data();
var country = data.find(x => x.Designation == $("#Search").val());
console.log("Country")
if (country) {
var request = $.post('/CountryManagement/Edit', { id: country.CountryID });
request.success(function (data) {
$("#form-content").html(data);
});
}
}
}
HTML code generated on page load (autocomplete and dropdown only)
<div class="form-group">
<label class="control-label col-md-2" for="Search_Country">Search Country</label>
<div class="col-md-3">
<span tabindex="-1" role="presentation" class="k-widget k-autocomplete k-header k-state-default k-state-hover"><input data-val="true" data-val-length="Description must have between 1 and 150 characters" data-val-length-max="150" data-val-length-min="1" id="Search" name="Search" type="text" data-role="autocomplete" class="k-input" autocomplete="off" role="textbox" aria-haspopup="true" aria-disabled="false" aria-readonly="false" aria-owns="Search_listbox" aria-autocomplete="list" has-focus="false" style="width: 100%;"><span class="k-icon k-loading" style="display:none"></span></span>
</div>
</div>
<br>
<br>
<div class="form-group">
<label class="control-label col-md-2" for="Country">Country</label>
<div class="col-md-3">
<span class="k-widget k-combobox k-header"><span tabindex="-1" unselectable="on" class="k-dropdown-wrap k-state-default"><input name="CountryID_input" class="k-input" type="text" autocomplete="off" title="" role="combobox" aria-expanded="false" tabindex="0" aria-disabled="false" aria-readonly="false" aria-autocomplete="list" aria-owns="CountryID_listbox" has-focus="false" style="width: 100%;"><span tabindex="-1" unselectable="on" class="k-select"><span unselectable="on" class="k-icon k-i-arrow-s" role="button" tabindex="-1" aria-controls="CountryID_listbox">select</span></span></span><input data-val="true" data-val-number="The field CountryID must be a number." id="CountryID" name="CountryID" type="text" value="0" data-role="combobox" aria-disabled="false" aria-readonly="false" has-focus="false" style="display: none;"></span>
<span class="field-validation-valid text-danger" data-valmsg-for="CountryID" data-valmsg-replace="true"></span>
</div>
</div>
HTML code generated on partialview reload (autocomplete and dropdown only)
<div class="form-group">
<label class="control-label col-md-2" for="Search_Country">Search Country</label>
<div class="col-md-3">
<input data-val="true" data-val-length="Description must have between 1 and 150 characters" data-val-length-max="150" data-val-length-min="1" id="Search" name="Search" type="text" value="South Africa">
</div>
</div>
<br>
<br>
<div class="form-group">
<label class="control-label col-md-2" for="Country">Country</label>
<div class="col-md-3">
<input data-val="true" data-val-number="The field CountryID must be a number." id="CountryID" name="CountryID" type="text" value="1003">
<span class="field-validation-valid text-danger" data-valmsg-for="CountryID" data-valmsg-replace="true"></span>
</div>
</div>
I'm not sure if this is an issue with ASP.Net MVC partialviews, Kendo controls or some scripts that should be re-run when the partialview reloads.
Can someone please help me?
After numerous failed attempts and fruitsless digging in the deep end of Telerik forums, i finally found out what the problem is.
Kendo widgets in partial views should not use deferred initialization.
#(Html.Kendo().AutoCompleteFor(m => m.Search)
///.. code removed to reduce complexity
.Events(e => e.Change("onChange")).Deferred()
)
When the view is loaded through as server request, it renders properly because in the end of the layout file, all the widgets with deferred initialization are initialized using #Html.Kendo().DeferredScripts(). However when the partial view is reloaded via ajax, the deferred scripts initialization never happens because the scripts are not re-run.
Adding #Html.Kendo().DeferredScripts() to the partial view solves the problem of ajax reload but becomes and issue on server loading because: 1 - The deferred initialization would be running twice, and 2 - Because kendo widgets have jquery dependencies and would be running before the jquery scripts are included in the page.
The solution i found was to not deffer the initialization of the widgets, however this would take us back to the point above regarding the jquery dependencies. And as much as i tried to avoid it, the only thing that really worked was to include jquery in the page header. All of the other scripts (validation, kendo, custom, etc) are still at the bottom but the main jquery script is at the top. And now my partial views load perfectly on server or ajax request.
TL;DR;
Do not use deferred initialization in partial views
Move jquery.min.js to the top of the page.
Hopefully there is a better way to do it but for now it does the trick.
So I was searching the forums and couldn't find a suitable fix either. But i did the following and it seems to work just fine. Basically if the partial is rendered normally then the layout view handles the deferred scripts, but if the request is through AJAX then the partial view will go ahead and render them.
I put this at the bottom of my partial:
#if (Context.Request.IsAjaxRequest())
{
<div id="kendo-scripts">
#Html.Kendo().DeferredScripts()
</div>
}
FYI, leave the .Deffered() at the end of your kendo object also in case that wasn't apparent.
Check for any page script initialization errors!
I was running into the same problem here and burned 3 days on it, the issue for me ended up being there was a page initialization script script around the no MutationObserver not being available in older safari browser. After adding a polyfill and fixing init error, dynamically injected ajax content with Kendo controls worked fine with no defer needed. Hopefully this saves someone else some frustration.
This init error affected jquery's ready initializer callback for any ajax content which Telerik relies upon to render each control in the script block that it emits.

Keep menu selection throw views

I'm using mvc to go to an index that returns a partial view then render it in the body of a layout, then the different parts of the view (edit, add, delete)I use ajax and angular to render different parts of it. So I've got one index with different parts (edit, delete, add) that render the corresponding components and update them throw ajax. The thing is that I only want to render the section in the layout corresponding to the partial view, I mean in the renderbody() where the partial is rendered. But I dont want the header of the layout to to postback in order to mantain the options selected.
Here is an image:
This is the layout, the usual mvc layout:
<!DOCTYPE html>
<html lang="es">
<head>
</head>
<body>
<header>
<div class="content-wrapper">
<div class="float-left">
<p class="site-title">
#Html.ActionLink("su logotipo aquí", "Index", "Home")</p>
</div>
</div>
<select>
<option>Option 1</option>
<option>Option 2</option>
</select>
</header>
<div id="body">
#RenderSection("featured", required: false)
<section class="content-wrapper main-content clear-fix">
#RenderBody()
</section>
</div>
<footer>
<div class="content-wrapper">
<div class="float-left">
<p>© #DateTime.Now.Year - Mi aplicación ASP.NET MVC</p>
</div>
</div>
</footer>
#Scripts.Render("~/bundles/jquery")
#RenderSection("scripts", required: false)
</body>
My View:
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>holaaaaaaaaaaaaaaaaaa</h2>
My controller:
public ActionResult Index()
{
return PartialView();
}
In short:
I need to know how to use partial views, to render it in the layout, mantaining the options selected and not doing post back to better look of the page.
If you don't find a good solution to your problem, consider implementing bootstrap tabs http://getbootstrap.com/javascript/#tabs
I've had a similar problem and without finding a solution I've switched from select box to tabs.
Basically you play with tabs and ng-includes like this:
<ul class="nav nav-tabs">
<li class="active"><a href="" data-toggle="tab">TabName1
<ng-include src="'myFirstPartialTemplate.html'">
</a></li>
<li><a href="" data-toggle="tab">TabName2
<ng-include src="'mySecondPartialTemplate.html'">
</a></li>
</ul>
If your view is a partial view, then it should not have the property 'Layout' set.
I would do the following:
Make your index page return a View:
public ActionResult Index()
{
return View();
}
Create a another action to return your partial:
public ActionResult MyPartial()
{
return PartialView();
}
In your index page, if you wish, render your partial in the body.
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>holaaaaaaaaaaaaaaaaaa</h2>
#Html.Partial("MyPartial")
Not sure if this is what you need, but I hope it helps.

Render Dynamic String as Razor

I'm trying to render a string that is stored in my database as if it were from a CSHTML file. Here is a sample string that I'd like to render:
<footer>
<div class="content-wrapper">
<div class="float-left">
<p>© #DateTime.Now.Year - My ASP.NET MVC Application</p>
</div>
</div>
</footer>
Notice that "#DateTime.Now.Year"? Well, if this were stored in a database, how would I render this into a view and have that part of it actually render as 2014 (or whatever year it is that you're reading this)?
You can use RazorEngine (NuGet package "RazorEngine") for this.
Package Manager Console:
PM> install-package razorengine
In your code:
string template = GetYourTemplateFromDatabase();
string content = RazorEngine.Razor.Parse(template, null);
If you want to add this output to your actual view you would have to add it as an IHtmlString or use #Html.Raw(ViewBag.Content):
Controller code (for IHtmlString):
ViewBag.DatabaseCode = MvcHtmlString.Create(content);
View code:
<div>
#ViewBag.DatabaseCode
</div>
you need define a model in razor
this is a good example http://weblogs.asp.net/scottgu/asp-net-mvc-3-new-model-directive-support-in-razor
If I understand correctly, you're storing that whole HTML snippet in the database? You could do a simple String.Replace on the string you get from the database.
<footer>
<div class="content-wrapper">
<div class="float-left">
<p>© {{YEAR}} - My ASP.NET MVC Application</p>
</div>
</div>
</footer>
And then in the view :
#Html.Raw(Model.Footer.Replace("{{YEAR}}", DateTime.Now.Year))

Categories