How to render events in FullCalendar from JSON in ASP.NET MVC? - javascript

I've been able to get FullCalendar to load in my webpage but I can't seem to successfully pass my test JSON data to the calendar and have it render events. I'm not sure what I'm doing wrong.
I'm following this website's example and I even downloaded their source code and was able to run it successfully in my dev environment. My code seems to almost completely mirror their's yet I still can't render events. I even went back and added javascript files to my bundles just in case that was the issue but to no success.
Any ideas?
Bundles:
public class BundleConfig
{
// For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862
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*"));
// Use the development version of Modernizr to develop with and learn from. Then, when you're
// ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
"~/Scripts/modernizr-*"));
bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
"~/Scripts/bootstrap.js",
"~/Scripts/respond.js"));
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/site.css",
"~/Content/themes/base/jquery.ui.all.css",
"~/Content/fullcalendar.css"));
/*Kendo UI Instructions that were followed
* http://docs.telerik.com/kendo-ui/aspnet-mvc/asp-net-mvc-5
*/
bundles.Add(new ScriptBundle("~/bundles/kendo").Include(
"~/Scripts/kendo/2016.2.714/kendo.webcomponents.min.js",
// "~/Scripts/kendo/kendo.timezones.min.js", // uncomment if using the Scheduler
"~/Scripts/kendo/2016.2.714/kendo.aspnetmvc.min.js",
"~/Scripts/kendo/2016.2.714/jquery.min.js",
"~/Scripts/kendo/2016.2.714/kendo.ui.core.min.js",
"~/Scripts/kendo/2016.2.714/kendo.calendar.min.js",
"~/Scripts/kendo/2016.2.714/kendo.popup.min.js",
"~/Scripts/kendo/2016.2.714/kendo.datepicker.min.js"));
bundles.Add(new StyleBundle("~/Content/kendo/css").Include(
"~/Content/kendo/2016.2.714/kendo.common-bootstrap.min.css",
"~/Content/kendo/2016.2.714/kendo.bootstrap.min.css",
"~/Content/kendo/2016.2.714/kendo.common.min.css",
"~/Content/kendo/2016.2.714/kendo.defualt.min.css"));
bundles.Add(new ScriptBundle("~/bundles/fullcalendar").Include(
"~/Scripts/jquery-ui-1.12.0.min.js",
"~/Scripts/moment.min.js",
"~/Scripts/fullcalendar.min.js"));
bundles.IgnoreList.Clear();
}
_Layout:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Time Zone Event Calendar</title>
#Styles.Render("~/Content/kendo/css")
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/kendo")
#Scripts.Render("~/bundles/fullcalendar")
</head>
<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"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
#Html.ActionLink("Time Zone Event Calendar", "Index", "Home", new { area = "" }, new { #class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>#Html.ActionLink("Home", "Index", "Home")</li>
<li>#Html.ActionLink("About", "About", "Home")</li>
<li>#Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
</div>
</div>
</div>
<div class="container body-content">
#RenderBody()
<hr />
<footer>
<p>© #DateTime.Now.Year - Time Zone Event Calendar</p>
</footer>
</div>
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
</body>
</html>
Index:
#{
ViewBag.Title = "Home Page";
}
<head>
#section scripts{
<script type="text/javascript">
$(document).ready(function ()
{
$('#calendar').fullCalendar(
{
header:
{
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
editable: false,
events: "/home/loadevents/"
})
});
</script>
<script type="text/javascript">
$(document).ready(function () {
$("#pickDateTime").kendoDateTimePicker({
culture: "es-Es",
interval: 1,
format: "yyyy/MM/dd hh:mm tt",
parseFormats: ["MMMM yyyy", "HH:mm"]
});
});
</script>
}
</head>
<body>
<div id="headerBar">
<div id="datepicker">
<form method="post">
<input id="pickDateTime" name="DateTimePicker" />
<input type="submit" value="Add" />
</form>
</div>
</div>
<div id="calendar"></div>
</body>
HomeController:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
public ActionResult LoadEvents (double start, double end)
{
var fromDate = ConvertFromUnixTimestamp(start);
var toDate = ConvertFromUnixTimestamp(end);
var eventList = GetEvents();
var rows = eventList.ToArray();
return Json(rows, JsonRequestBehavior.AllowGet);
}
private List<CalendarEventsViewModel> GetEvents()
{
List<CalendarEventsViewModel> eventList = new List<CalendarEventsViewModel>();
CalendarEventsViewModel newEvent = new CalendarEventsViewModel
{
ID = "1",
EventName = "Event 1",
StartDateString = DateTime.Now.AddDays(1).ToString("s"),
EndDateString = DateTime.Now.AddDays(1).ToString("s"),
AllDay = false
};
eventList.Add(newEvent);
newEvent = new CalendarEventsViewModel
{
ID = "1",
EventName = "Event 3",
StartDateString = DateTime.Now.AddDays(2).ToString("s"),
EndDateString = DateTime.Now.AddDays(3).ToString("s"),
AllDay = false
};
eventList.Add(newEvent);
return eventList;
}
private static DateTime ConvertFromUnixTimestamp(double timestamp)
{
var origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
return origin.AddSeconds(timestamp);
}
}
CalendarEventsViewModel:
public class CalendarEventsViewModel
{
public string ID { get; set; }
public string EventName { get; set; }
public string EventText { get; set; }
public string StartDateString { get; set; }
public string EndDateString { get; set; }
public bool AllDay { get; set; }
}

I think you have made the same mistake I did when I first set it up, the example you are looking at only works for version one of FullCalendar. In version two it's not a unix timestamp your LoadEvents action receives.
It's a moment object that is passed to the action, if you remove your ConvertFromUnixTimestamp method and change your start and end parameters from double to DateTime I think it will start working.
If you break point your LoadEvents action without making any changes I am pretty confident it's not even being called.
Your property names should match those of the event object otherwise it will treat them like non standard fields.

Related

ajax mvc html: jquery val not preventing call to api

When clicking a button I am calling a web api with ajax. My form is using JqueryVal, to make form validations, according to my viewmodel data annotations.
My problem is that when I click the button "Listo" in my form, it calls my API, inspite of jqueryval is marking an error( selecting a file is required)
This is my code:
My viewmodel that contains data annotations(the dataannotations are used along with the jquery.validate.js and jquery.validate.unobtrusive.js. As you can see, it is working, but is not preventing the API from being called):
public class CursoViewModel
{
public Guid Id { get; set; }
[MaxLength(125)]
public string Titulo { get; set; }
[Required]
public string Descripcion { get; set; }
[Required(ErrorMessage ="selecciona una imagen para tu curso")]
[DataType(DataType.Upload)]
public HttpPostedFileBase Imagen { get; set; }
}
The class posted to my api
public class person
{
public string name { get; set; }
public string surname { get; set; }
}
The Api code
[HttpPut]
[Route("api/ProfesorCurso/test")]
public string Put(person p)
{
return p.name + p.surname;
}
My View
#model project.ViewModels.CourseViewModel
<form id="Editcurso" method="post" action="#">
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "Please fix the following errors.")
<div class="container">
<div class="form-group">
#Html.LabelFor(c=>c.Titulo)
#Html.TextBoxFor(c => c.Titulo, new {id="titulo", #class="form-control"})
#Html.ValidationMessageFor(m => m.Titulo)
</div>
<div class="form-group">
#Html.LabelFor(c => c.Descripcion)
#Html.TextAreaFor(c => c.Descripcion, new {id="descripcion", #class = "form-control" })
#Html.ValidationMessageFor(m => m.Descripcion)
</div>
<div class="thumbnail" id="imagencurso"></div>
<div class="form-group">
#Html.LabelFor(m => m.Imagen)
#Html.TextBoxFor(m => m.Imagen, new {id="imagen" ,type = "file", data_rule_validCustomer = "true" })
#Html.ValidationMessageFor(m => m.Imagen)
</div>
<button id="submiter" type="submit" class="btn btn-primary">Listo!</button>
</div>
</form>
The scripts in the view
#section scripts
{
#Scripts.Render("~/bundles/jqueryval")
<script>
$(document).ready(function () {
$("#submiter").click(function () {
jQuery.support.cors = true;
var person = new Object();
person.name = "Sourav";
person.surname = "Kayal";
$.ajax({
url: '/api/ProfesorCurso/test',
type: 'PUT',
dataType: 'json',
data: person,
success: function (data) {
console.log(data);
return false;
},
error: function (x, y, z) {
alert('error al postear');
return false;
}
});
});
});
</script>
}
What can I do to prevent ajax to call my api when clicking my form button, if there are Jquery validation errors?
thanks
You should be handling the .submit() event of the form, and then your can check .valid(), and if not cancel the ajax call. Note you should also be cancelling the default submit.
$('#Editcurso').submit(e) {
e.preventDefault(); // prevent the default submit
if (!$(this).valid()) {
return; // exit the function and display the errors
}
....
$.ajax({
....
});
}
As a side note, there is no point adding new { id="titulo" } etc - the HtmlHelper methods that generate form controls already add an id attribute based on the property name

Uncaught TypeError: Cannot read property 'data' of undefined jquery Jtable

I've been investigating for this issue for more than 12 hours with no clue for any solution. I have good knowledge about jtable and I've been using it for long time. I have an ordinary div which I want to build it using jtable, so I copied the code from an old working sample in my application and edited it, but there is a javascript error appear in the console which prevents the data to show in the table:
Uncaught TypeError: Cannot read property 'data' of undefined jquery Jtable
here is my html page:
#model Tuple<List<SIO.Core.Entities.Group>, List<SIO.Core.Entities.WorkFlow>>
#section JavaScript
{
<script type="text/javascript" src="#Url.Content("/Scripts/GroupHandler.js")"></script>
<script type="text/javascript" src="#Url.Content("/Scripts/jquery-ui.js")"></script>
<script type="text/javascript" src="#Url.Content("/Scripts/jquery.jtable.js")"></script>
}
#{
ViewBag.Title = "المجموعات";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div id="divBackgroundtask" style="display: none;">
</div>
<div id="indx_divtask">
<section class="col-md-8 taskPoolfilterSection">
<div class="form-group">
<div class="border-top">
</div>
<div id="filter" class="panel-body margin-bottom">
<header class="panel-heading containt-border">
#ViewBag.Title
</header>
</div>
</div>
<!-- /.panel-body -->
<div id="divPleaseWaittask" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="load_div col-sm-offset-2 col-sm-5">
<div class=" row col-sm-2 col-sm-offset-9">
<img src="~/Images/Loading.gif" />
</div>
<div class="row col-sm-12 txt_wait">
<b>برجاء الإنتظار حتى إكمال العملية</b>
</div>
</div>
</div>
</section>
<div id="GroupsContainer" class="table-responsive">
</div>
And here is my javascript code to build jtable:
(document).ready(function () {
$('#GroupsContainer').jtable({
paging: true,
sorting: true,
messages: {
close: 'اغلاق',
pagingInfo: 'عرض {0}-{1} من {2}',
pageSizeChangeLabel: 'تعداد الصف',
noDataAvailable: 'لا يوجد بيانات للعرض!',
gotoPageLabel: 'الذهاب الى صفحة',
serverCommunicationError: 'حدث خطأ ما اثناء الإتصال...',
},
actions: {
//listAction: '/TaskPool/GetTasks?isAdmin=' + IsAdmin,
listAction: function (postData, jtParams) {
// alert("Loading...");
PleaseWaitDialogtask.show(true);
return $.Deferred(function ($dfd) {
$.ajax({
url: '/Group/GetAllGroups?' + 'jtStartIndex=' + jtParams.jtStartIndex + '&jtPageSize=' + jtParams.jtPageSize + '&jtSorting=' + jtParams.jtSorting,
type: 'Get',
dataType: 'json',
data: postData,
success: function (data) {
$dfd.resolve(data);
PleaseWaitDialogtask.show(false);
},
error: function () {
$dfd.reject();
}
});
});
},
},
fields: {
ID: {
key: true,
list: false
},
GroupName: {
title: 'اسم المجموعة'//,
//width: '40%'
},
GroupDisc: {
title: 'وصف المجموعة'//,
//width: '40%'
},
Link: {
title: '',
display: function (data) {
if (data.isRedirect) {
window.location.href = data.redirectUrl;
}
}
},
}
});
$('#GroupsContainer').jtable('load');
$('.jtable')[0].className = $('.jtable')[0].className + " table table-striped table-bordered table-hover";
});
This is the line which caused the error:
$dfd.resolve(data);
And here is my action method to retrieve the records:
[HttpGet]
public JsonResult GetAllGroups(int jtStartIndex = 0, int jtPageSize = 0, string jtSorting = null, string rangeSt = "", string rangeEd = "")
{
try
{
LogHelpper.LogMessage("GroupContorller GetAllSystemUsers Post Method Started", EventLogEntryType.Information, log);
GroupManager groupManager = new GroupManager();
List<Group> groups = groupManager.SkipAndTake(jtStartIndex, jtPageSize);
List<GroupCustomViewModel> groupCustomViewModel = groups.Select(group => new GroupCustomViewModel(group)).ToList();
LogHelpper.LogMessage("GroupContorller GetAllGroups Post Method Ended", EventLogEntryType.Information, log);
return Json(new { Result = "OK", Records = groupCustomViewModel , TotalRecordCount = groupCustomViewModel .Count }, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
LogHelpper.LogMessage("Error Message", EventLogEntryType.Error, log);
LogHelpper.LogException(ex, EventLogEntryType.Error, log);
return Json(new { Result = "ERROR", Message = ex.Message }, JsonRequestBehavior.AllowGet);
}
}
And here is my model:
public class GroupCustomViewModel
{
#region properties
/// <summary>
/// Gets or sets the GoupIDPK.
/// </summary>
/// <value>The GoupIDPK.</value>
public int GoupIDPK { get; set; }
/// <summary>
/// Gets or sets the GroupName.
/// </summary>
/// <value>The GroupName.</value>
public string GroupName { get; set; }
/// <summary>
/// Gets or sets the GroupDisc.
/// </summary>
/// <value>The GroupDisc.</value>
public string GroupDisc { get; set; }
public string EditHyperlink { get; set; }
public string DeleteHyperlink { get; set; }
public string DetalisHyperlink { get; set; }
public bool DefaultGroup { get; set; }
#endregion
}
Sorry if the question is too long but I don't know where the error would be so I
posted all code required to do the task.
Finally I found where the problem is!! ... In jTable definition at fields sectionID but the model field name is GroupIDPK so changing jTable field ID to GroupIDPK solved the problem

How to use Jquery/Ajax with asp.net MVC 4 with partial view and action with model

I am new to both asp.net MVC and JQuery so be gentle.
I am trying to use a HTTP Post to update my contact form, used to send an email, using AJAX. I have seen lots of posts but what I want seems specific and I cant seem to find anything relevant.
The down low: I have a layout page which has the header, renders the body and has my footer in. My footer contains the form I want to submit. I want to submit this form without refreshing the whole page. The layout page:
<div id="footer">
#{Html.RenderAction("Footer", "Basic");}
</div>
<p id="p"></p>
I have a model for this form to send an email.
namespace SimpleMemberShip.Models
{
public class EmailModel
{
[Required, Display(Name = "Your name")]
public string FromName { get; set; }
[Required, Display(Name = "Your email"), EmailAddress]
[StringLength(100, ErrorMessage = "The email address entered is not valid")]
public string FromEmail { get; set; }
[Required]
public string Message { get; set; }
}
The footer:
<h2> footer yo !</h2>
#Html.ValidationSummary()
<fieldset>
<legend>Contact Me!</legend>
<ol>
<li>
#Html.LabelFor(m => m.FromEmail)
#Html.TextBoxFor(m => m.FromEmail)
</li>
<li>
#Html.LabelFor(m => m.FromName)
#Html.TextBoxFor(m => m.FromName)
</li>
<li>
#Html.LabelFor(m => m.Message)
#Html.TextBoxFor(m => m.Message)
</li>
</ol>
<button id="submit"> Submit </button>
</fieldset>
controller:
[ChildActionOnly]
public ActionResult Footer()
{
return PartialView("~/Views/Shared/_Footer.cshtml");
}
[HttpPost]
public ActionResult Footer(EmailModel model)
{
return PartialView("~/Views/Shared/_Footer.cshtml");
}
I want to use the model validation and everything to be the same or similar as if the form was posted normally through the server.
Edit:
My new code, which works great! but it only works once, when the button is clicked again nothing happens. Anyone know why?
<script type="text/javascript">
$("#submit").click(function () {
$("#footer").html();
var url = '#Url.Action("Footer", "Basic")';
$.post(url, { FromName: $("[name=FromName]").val(), FromEmail: $(" [name=FromEmail]").val(), Message: $("[name=Message]").val() }, function (data) {
$("#footer").html(data);
});
var name = $("[name=FromName]").val();
$("#p").text(name);
});
</script>
new Edit:
did some research and using
$("#submit").live("click",function () {
instead of
$("#submit").click(function () {
seemed to do the trick.
<script type="text/javascript">
$("#submit").live("click",function () {
$('.validation-summary-errors').remove();
var url = '#Url.Action("Footer", "Basic")';
$.post(url, { FromName: $("[name=FromName]").val(), FromEmail: $("[name=FromEmail]").val(), Message: $("[name=Message]").val() }, function (data) {
$("#footer").html(data);
});
});
</script>
ended up with this but will try the "serialize()" option next time.
controller was changed to this without the [ChildActionOnly] and works perfect now
[HttpPost]
public ActionResult Footer(EmailModel model)
{
return PartialView("~/Views/Shared/_Footer.cshtml");
}
Thank you everyone that helped!
Change the [ChildActionOnly] to [HttpGet] in the controller
You can pass model data to controller by doing the following steps
1. Get the input values on click of submit and sent to the Footer action in controller
$("#submit").click(function () {
var FromEmailValue = $('#FromEmail').val();
var FromNameValue = $('#FromName').val();
var MessageValue = $('#Message').val();
var url = '#Url.Action("Footer", "Basic")';
$.ajax({
url: urlmodel,
data: { FromName: FromNameValue, FromEmail: FromEmailValue, Message: MessageValue},
cache: false,
type: "POST",
success: function (data) {
do something here
}
error: function (reponse) {
do something here
}
});
});
In the controller
``
[HttpGet]
public ActionResult Footer()
{
return PartialView("~/Views/Shared/_Footer.cshtml");
}
[HttpPost]
public ActionResult Footer(string FromName = "", string FromEmail = "", string Message = "")
{
//for ajax request
if (Request.IsAjaxRequest())
{
do your stuff
}
}

DotNet HighChart not populating

I am new to MVC and trying to use DotNet High Chart for the first time. I am following this tutorial in Visual Studios MVC 5.
My Bundles :
public class BundleConfig
{
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",
"~/Scripts/respond.js"));
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/site.css"));
bundles.Add(new Bundle("~/bundles/highchart").Include(
"~/Scripts/Highcharts-4.0.1/js/highchart.js"));
}
}
}
My Model:
namespace Charts2.Models
{
public class TransactionCount
{
public string MonthName { get; set; }
public int Count { get; set; }
}
}
My Controller :
namespace Charts2.Controllers
{
public class ChartSampleController : Controller
{
// GET: ChartSample
public ActionResult Index()
{
//create a collection of data
var transactionCounts = new List<TransactionCount>{
new TransactionCount(){ MonthName="January", Count=30},
new TransactionCount(){ MonthName="Febuary", Count=40},
new TransactionCount(){ MonthName="March", Count=4},
new TransactionCount(){ MonthName="April", Count=35},
};
// modify data type to make it of array types
var xDataMonths = transactionCounts.Select(i => i.MonthName).ToArray();
var yDataCounts = transactionCounts.Select(i => new object[] { i.Count }).ToArray();
//instanciate an object of the high charts type
var chart = new Highcharts("chart")
// define the type of chart
.InitChart(new Chart { DefaultSeriesType = ChartTypes.Line})
//overall title of the chart
.SetTitle(new Title { Text = "Incoming Transactions per hour"})
//small label below the main title
.SetSubtitle(new Subtitle { Text = "Accounting"})
// load the x values
.SetXAxis(new XAxis {Categories = xDataMonths})
// set the y title
.SetYAxis(new YAxis { Title = new YAxisTitle { Text = "Number of Transactions"}})
.SetTooltip(new Tooltip{
Enabled = true,
Formatter = #"function() { return '<b>'+this.series.name +'</b><br/>'+this.x+': '+this.y;}"
})
.SetPlotOptions(new PlotOptions{
Line = new PlotOptionsLine {
DataLabels = new PlotOptionsLineDataLabels {
Enabled = true
},
EnableMouseTracking = false
}
})
//load y values
.SetSeries(new []
{
new Series {Name = "Hour", Data = new Data(yDataCounts)},
});
return View(chart);
}
}
}
and my view:
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#model DotNet.Highcharts.Highcharts
<p> My Chart </p>
#(Model)
My shared _Index:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title - My ASP.NET Application</title>
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/highchart")
</head>
<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"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
#Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { #class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>#Html.ActionLink("Home", "Index", "Home")</li>
<li>#Html.ActionLink("About", "About", "Home")</li>
<li>#Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
#Html.Partial("_LoginPartial")
</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/bootstrap")
#RenderSection("scripts", required: false)
Whenever I run the application the chart does not generate at all. I had followed the tutorial and cannot understand where I am going wrong. On the console I am getting the following exception:
Uncaught ReferenceError: Highcharts is not defined
Any advice would be greatly appreciated
Thanks
Can you please post entire view code. As in your current view you are not adding high chart bundle to view
Some thing like
#Scripts.Render("~/bundles/highchart")
I've realised where I was going wrong. I was missing an s at the end of the bundle name, I changed the bundle:
bundles.Add(new ScriptBundle("~/bundles/highcharts").Include(
"~/Scripts/Highcharts-4.0.1/js/highcharts.js"
));
and updated the _index according and now it works.

Add call to controller on _Layout?

I have a layout page which is used by my MVC site. It has no models or any related controller methods.
But now I want to add a "Search" box at the top. I can't add a normal "Form" because it get's over ridden, or overrides any other forms on the content pages. So I was thinking I might have to do it with Javascript... call a javascript function that then sends the query to a controller, and then moves the user to the result screen.
Is this the right way to do it? Or can I somehow use a normal controller method call from my layout page?
Let's assume you have these models:
public class SearchModel
{
public string SearchTerm { get; set; }
}
public class LoginModel
{
public string UserName { get; set; }
public string Password { get; set; }
}
And that you also had these controllers:
public class HomeController : Controller
{
public ActionResult Search(SearchModel model)
{
return View();
}
}
public class AccountController : Controller
{
public ActionResult Login(LoginModel model)
{
return View();
}
}
You could use something like this as a layout view:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>#ViewBag.Title</title>
</head>
<body>
#using(Html.BeginForm("search", "home", FormMethod.Post, new {}))
{
<input type="search" name="SearchTerm" placeholder="Find..." />
<button type="submit">GO</button>
}
#if(!Request.IsAuthenticated)
{
using(Html.BeginForm("login", "account", FormMethod.Post, new {}))
{
<input type="text" name="UserName" placeholder="..." />
<input type="password" name="Password" placeholder="..." />
<button type="submit">GO</button>
}
}
#RenderBody()
</body>
</html>
The model binder is smart enough to match up request parameters to the correct model properties, even if you don't use the #Html helpers to create your HTML controls. The problem you'll run into is what to do with, say, invalid login attempts. Seems like the typical workflow is to have a normal login action - that lets you dump the user to a proper login page if they enter invalid credentials in, say, a navbar login form.
Another option is to embed the search and login forms as child actions:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>#ViewBag.Title</title>
</head>
<body>
#Html.Action("search", "home")
#Html.Action("login", "account")
#RenderBody()
</body>
</html>
If you go that route, you would modify the controller to return partial views. Here's one implementation of an AccountController:
public class AccountController : Controller
{
[HttpGet, AllowAnonymous]
public ActionResult Login(string returnUrl = "")
{
return View();
}
[HttpPost, AllowAnonymous]
public ActionResult Login(LoginModel model)
{
if(ModelState.IsValid)
{
/* valid user credentials */
return RedirectToAction("index", "home");
}
return View(model);
}
[AllowAnonymous, ChildActionOnly]
public ActionResult NavbarLogin()
{
return PartialView();
}
}
Notice the last action method; marking it as ChildActionOnly prevents the action from being directly requested by the browser. The view for that method might look like this:
#model Your.Fully.Qualified.Namespace.Models.LoginModel
#using(Html.BeginForm("login", "account", FormMethod.Post, new { }))
{
#Html.LabelFor(m => m.UserName)
#Html.TextBoxFor(m => m.UserName)
#Html.ValidationMessageFor(m => m.UserName)
#Html.LabelFor(m => m.Password)
#Html.PasswordFor(m => m.Password)
#Html.ValidationMessageFor(m => m.Password)
<button type="submit">Login</button>
}
The advantage of the strongly-typed helpers is that MVC will create the validation data- attributes that the Unobtrusive Validation library leverages; include the jqueryval bundle on the layout and any view with strongly-typed helpers gets client-side validation automatically.
In this example, the "navbar login" posts to the normal login action, so invalid credentials will result in the user being shown the login page, rather than the page they were originally viewing.

Categories

Resources