Using jquery to set asp.net mvc model values - javascript

I have a gap in my understanding. I have two view screens, one successfully gets a value from a devexpress selection grid but one doesn't... and I don't understand what I am doing differently.
When I use firebug I can't find where the model is set in the DOM.
The following works:
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel.DataAnnotations;
namespace EtracsWeb.Areas.IO.Models
{
public class VoyageInputModel
{
[Required(ErrorMessage = "Value must be supplied")]
[Display(Name = "Show Received Voyages")]
public bool ShowReceivedVoyages { get; set; }
public string VoyageIDS { get; set; }
}
}
being used in the view (which works)...here is a fragment of the view:
#using EtracsWeb.Areas.IO.Models;
#model VoyageInputModel
#{
ViewBag.Title = "Voyage (Receive/UnReceive/etc..)";
Layout = "~/Views/Shared/_LayoutMenu.cshtml";
}
#* MUST go here and NOT at end or code won't work *#
<script type="text/javascript">
//This is the value from the devExpress Selection Grid...
function OnSelectionChanged(s, e) {
s.GetSelectedFieldValues("VoyageID", GetSelectedFieldValuesCallback);
}
//This is the value from the InputModel...notice it is different...
//This is why we need this two step process.
function GetSelectedFieldValuesCallback(values) {
// voyage_ids = values;
//alert(values);
document.getElementById('VoyageIDS').value = values;
//alert(document.getElementById('VoyageIDS').value)
}
</script>
Notice I am getting the value from the OnSelection changed as one variable and setting in the inputModel as different name....this all works...
I am trying to do it with a second view and the code dies where I try to access the variable in the model using a getElementbyID .... originally I was trying to use an int...but I switched it to a string...but neither work....
Where in the heck is the model in the DOM? How can I use Firebug to view the #model values (from asp.net mvc)???
Any ideas where I went wrong on the second window?
Here is the second inputmodel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel.DataAnnotations;
namespace EtracsWeb.Areas.Vehicle.Models
{
public class BookMarkListInputModel
{
public string SelectedBookMarkID { get; set; }
public int BookMarkID { get; set; }
public IEnumerable<BookMark> BookMarks { get; set; }
}
}
and the second view fragment:
#using EtracsWeb.Areas.Vehicle.Models
#model BookMarkListInputModel
#{
ViewBag.Title = "List";
Layout = "~/Views/Shared/_LayoutMenu.cshtml";
}
#* MUST go here and NOT at end or code won't work *#
<script type="text/javascript">
//This is the value used in the DevExpress Selection Grid
function OnSelectionChanged(s, e) {
s.GetSelectedFieldValues("BookMarkID", GetSelectedFieldValuesCallback);
}
//This is the variable from the InputModel...notice it can be different
//So we need to have this two step process.
function GetSelectedFieldValuesCallback(values) {
alert(values);
document.getElementById('SelectedBookMarkID').value = values;
alert(document.getElementById('SelectedBookMarkID').value)
}
function Success(data) {
// alert(data.ReturnMessage);
id1.innerHTML = data.ReturnMessage;
}
</script>

Related

Directing user to another page in ASP.Net MVC application leads to syntax error in auto-generated code

Snippet from my _layout.cshtml file
<body>
<!--
NAVBAR
-->
<div class="navBar">
<input id="homeButton" type="submit" name="homeButton" value="Home"/>
<input id="toolsButton" type="submit" name="toolsButton" value="Tools"/>
<input id="contactButton" type="submit" name="contactButton" value="Contact Me"/>
<input id="supportButton" type="submit" name="supportButton" value="Support"/>
<input id="aboutButton" type="submit" name="aboutButton" value="About"/>
</div><!--TODO: STYLE THESE -->
<script>
const homeButton = document.getElementById("homeButton");
const toolsButton = document.getElementById("toolsButton");
const contactButton = document.getElementById("contactButton");
const supportButton = document.getElementById("supportButton");
const aboutButton = document.getElementById("aboutButton");
homeButton.addEventListener("click", () => {
window.location.href = "/";
});
toolsButton.addEventListener("click", () => {
window.location.href = "/Tools/Index"; // "/Tools" doesn't work either
});
contactButton.addEventListener("click", () => {
window.location.href = "/";
});
supportButton.addEventListener("click", () => {
window.location.href = "/";
});
aboutButton.addEventListener("click", () => {
window.location.href = "/";
});
</script>
The error generated when button clicked
Server Error in '/' Application.
Compilation Error
Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.
Compiler Error Message: CS1003: Syntax error, '>' expected
Source Error:
Line 29:
Line 30:
Line 31: public class _Page_Views_Tools_Index_cshtml : System.Web.Mvc.WebViewPage<LgbtqWebsiteNoDb.Models.Tool;> {
Line 32:
Line 33: #line hidden
Source File: c:\Users\marfx\AppData\Local\Temp\Temporary ASP.NET Files\root\ec7221e8\6a6fd7fe\App_Web_index.cshtml.f024d85f.citsmrxd.0.cs Line: 31
Detailed compiler output
C:\Program Files (x86)\IIS Express> "C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe" /t:library /utf8output /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_32\System.Web\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Web.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Data.DataSetExtensions\v4.0_4.0.0.0__b77a5c561934e089\System.Data.DataSetExtensions.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_32\System.Data\v4.0_4.0.0.0__b77a5c561934e089\System.Data.dll" /R:"C:\Users\marfx\AppData\Local\Temp\Temporary ASP.NET Files\root\ec7221e8\6a6fd7fe\assembly\dl3\87f9e4d5\000e9c93_3d27cf01\System.Web.Optimization.dll" /R:"C:\Users\marfx\AppData\Local\Temp\Temporary ASP.NET Files\root\ec7221e8\6a6fd7fe\App_global.asax.ewmqttqt.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Web.Extensions\v4.0_4.0.0.0__31bf3856ad364e35\System.Web.Extensions.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.ServiceModel.Activities\v4.0_4.0.0.0__31bf3856ad364e35\System.ServiceModel.Activities.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Web.Services\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Web.Services.dll" /R:"C:\Users\marfx\AppData\Local\Temp\Temporary ASP.NET Files\root\ec7221e8\6a6fd7fe\assembly\dl3\b5be25e0\003c87e2_1a87d401\System.Web.WebPages.Razor.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Web.ApplicationServices\v4.0_4.0.0.0__31bf3856ad364e35\System.Web.ApplicationServices.dll" /R:"C:\Users\marfx\AppData\Local\Temp\Temporary ASP.NET Files\root\ec7221e8\6a6fd7fe\assembly\dl3\77f8a528\001bc110_4318cf01\WebGrease.dll" /R:"C:\Users\marfx\AppData\Local\Temp\Temporary ASP.NET Files\root\ec7221e8\6a6fd7fe\assembly\dl3\7a6f1e22\0016534c_1a87d401\System.Web.Razor.dll" /R:"C:\Users\marfx\AppData\Local\Temp\Temporary ASP.NET Files\root\ec7221e8\6a6fd7fe\assembly\dl3\0bd5514f\8682d14f_c649d701\LgbtqWebsiteNoDb.dll" /R:"C:\Users\marfx\AppData\Local\Temp\Temporary ASP.NET Files\root\ec7221e8\6a6fd7fe\assembly\dl3\5eada7ec\003c87e2_1a87d401\System.Web.WebPages.dll" /R:"C:\Users\marfx\AppData\Local\Temp\Temporary ASP.NET Files\root\ec7221e8\6a6fd7fe\assembly\dl3\bfe09c51\003c87e2_1a87d401\System.Web.Helpers.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Runtime.Serialization\v4.0_4.0.0.0__b77a5c561934e089\System.Runtime.Serialization.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Core\v4.0_4.0.0.0__b77a5c561934e089\System.Core.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.VisualStudio.Web.PageInspector.Loader\v4.0_1.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Web.PageInspector.Loader.dll" /R:"C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.ServiceModel\v4.0_4.0.0.0__b77a5c561934e089\System.ServiceModel.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.ServiceModel.Activation\v4.0_4.0.0.0__31bf3856ad364e35\System.ServiceModel.Activation.dll" /R:"C:\Users\marfx\AppData\Local\Temp\Temporary ASP.NET Files\root\ec7221e8\6a6fd7fe\assembly\dl3\0103d10e\00c8d184_3aaece01\Antlr3.Runtime.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.ServiceModel.Web\v4.0_4.0.0.0__31bf3856ad364e35\System.ServiceModel.Web.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Drawing\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Drawing.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_32\System.EnterpriseServices\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.EnterpriseServices.dll" /R:"C:\Users\marfx\AppData\Local\Temp\Temporary ASP.NET Files\root\ec7221e8\6a6fd7fe\assembly\dl3\39611dac\001cbe16_536acd01\Microsoft.Web.Infrastructure.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.ComponentModel.DataAnnotations\v4.0_4.0.0.0__31bf3856ad364e35\System.ComponentModel.DataAnnotations.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.WorkflowServices\v4.0_4.0.0.0__31bf3856ad364e35\System.WorkflowServices.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.IdentityModel\v4.0_4.0.0.0__b77a5c561934e089\System.IdentityModel.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Activities\v4.0_4.0.0.0__31bf3856ad364e35\System.Activities.dll" /R:"C:\Users\marfx\AppData\Local\Temp\Temporary ASP.NET Files\root\ec7221e8\6a6fd7fe\assembly\dl3\129223b9\003c87e2_1a87d401\System.Web.WebPages.Deployment.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Xml.Linq\v4.0_4.0.0.0__b77a5c561934e089\System.Xml.Linq.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Xml\v4.0_4.0.0.0__b77a5c561934e089\System.Xml.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.CSharp\v4.0_4.0.0.0__b03f5f7f11d50a3a\Microsoft.CSharp.dll" /R:"C:\Users\marfx\AppData\Local\Temp\Temporary ASP.NET Files\root\ec7221e8\6a6fd7fe\assembly\dl3\b4261359\00cdd33c_1a87d401\System.Web.Mvc.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Web.DynamicData\v4.0_4.0.0.0__31bf3856ad364e35\System.Web.DynamicData.dll" /R:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Configuration\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll" /R:"C:\Users\marfx\AppData\Local\Temp\Temporary ASP.NET Files\root\ec7221e8\6a6fd7fe\assembly\dl3\dd04c433\00eff220_9da8d301\Newtonsoft.Json.dll" /out:"C:\Users\marfx\AppData\Local\Temp\Temporary ASP.NET Files\root\ec7221e8\6a6fd7fe\App_Web_index.cshtml.f024d85f.citsmrxd.dll" /D:DEBUG /debug+ /optimize- /w:4 /nowarn:1659;1699;1701;612;618 /warnaserror- "C:\Users\marfx\AppData\Local\Temp\Temporary ASP.NET Files\root\ec7221e8\6a6fd7fe\App_Web_index.cshtml.f024d85f.citsmrxd.0.cs" "C:\Users\marfx\AppData\Local\Temp\Temporary ASP.NET Files\root\ec7221e8\6a6fd7fe\App_Web_index.cshtml.f024d85f.citsmrxd.1.cs"
Microsoft (R) Visual C# Compiler version 4.8.4084.0
for C# 5
Copyright (C) Microsoft Corporation. All rights reserved.
This compiler is provided as part of the Microsoft (R) .NET Framework, but only supports language versions up to C# 5, which is no longer the latest version. For compilers that support newer versions of the C# programming language, see http://go.microsoft.com/fwlink/?LinkID=533240
c:\Users\marfx\AppData\Local\Temp\Temporary ASP.NET Files\root\ec7221e8\6a6fd7fe\App_Web_index.cshtml.f024d85f.citsmrxd.0.cs(31,106): error CS1003: Syntax error, '>' expected
c:\Users\marfx\AppData\Local\Temp\Temporary ASP.NET Files\root\ec7221e8\6a6fd7fe\App_Web_index.cshtml.f024d85f.citsmrxd.0.cs(31,106): error CS1519: Invalid token ';' in class, struct, or interface member declaration
I have tried to redirect the users to other pages via Razor with Response.Redirect("/Tools"); but this doesn't work either, throwing a different exception on the same line (compiler just picked a different character to throw on).
My Tools controller
using System.Collections.Generic;
using System.Web.Mvc;
using LgbtqWebsiteNoDb.Models;
using static LgbtqWebsiteNoDb.Models.Tool;
using Microsoft.Ajax.Utilities;
namespace LgbtqWebsiteNoDb.Controllers
{
public class ToolsController : Controller
{
private static readonly List<Tool> Tools = new List<Tool>()
{
new Tool
{
ToolName = "Hateful Countries Finder",
ReleaseDate = DateTime.Now.Date,
UpdateDate = DateTime.Now.Date, //GetLastUpdate(toolId:1), //TODO: Fix this method, it looks for the file in the wrong place
ToolId = 1,
ToolDesc = "A tool to find out which countries in the world have anti-Lgbtq+ laws which apply to you",
ToolThumbUrl = "",
ToolThumbAlt = ""
},
new Tool
{
ToolName = "Hateful Map",
ReleaseDate = DateTime.Now.Date,
UpdateDate = DateTime.Now.Date, //GetLastUpdate(toolId:2),
ToolId = 2,
ToolDesc = "A tool to show how many world countries have generic anti-Lgbtq laws",
ToolThumbUrl = "",
ToolThumbAlt = ""
}
};
public static int ToolCount = Tools.Count;
// GET: Tools/
public ActionResult Index()
{
ViewBag.Title = "Tools | Home";
return View();
}
// GET: Tools/HatefulCountriesFinder
public ActionResult HatefulCountriesFinder()
{
ViewBag.Title = "Tools | Hateful Countries";
return View();
}
// GET: Tools/HatefulMap
public ActionResult HatefulMap()
{
ViewBag.Title = "Tools | Hateful Map";
return View();
}
}
}
Tools model
public class Tool
{
/// <summary>
/// Getter and Setter for the name of a given tool
/// </summary>
public string ToolName { get; set; }
/// <summary>
/// Getter and Setter for the date the tool was released
/// </summary>
[DataType(DataType.Date)] public DateTime ReleaseDate { get; set; }
/// <summary>
/// Getter and Setter for the date the tool was last updated
/// </summary>
[DataType(DataType.Date)] public DateTime UpdateDate { get; set; }
/// <summary>
/// Getter and Setter for the tool ID
/// </summary>
public int ToolId { get; set; }
/// <summary>
/// Getter and Setter for the description of the tool
/// </summary>
public string ToolDesc { get; set; }
/// <summary>
/// Getter and Setter for the thumbnail of the tool image
/// </summary>
public string ToolThumbUrl { get; set; }
/// <summary>
/// Getter and Setter for the alt text of the thumbnail
/// </summary>
public string ToolThumbAlt { get; set; }
/// <summary>
/// Getter and Setter for the number of tools; used for enumeration
/// </summary>
public int ToolCount { get; set; }
/// <summary>
/// A method to update the tool, and change the last updated date
/// </summary>
/// <returns>DateTime</returns>
public static DateTime UpdateTool()
{
//TODO: Write the actual code for this
//TODO: Write new update DateTime to the appropriate file; See GetLastUpdate() for more
return DateTime.Now.Date;
}
}
}
Tools/Index.cshtml
#model LgbtqWebsiteNoDb.Models.Tool;
<!DOCTYPE html>
<html lang="en-GB">
<head>
<title>#ViewBag.Title</title>
<!-- Removed the bulk of the head -->
</head>
<body>
<div class="title">
</div>
<table>
#for (var i = 0; i < #Model.ToolCount; i++)
{
<tr>
<td>
<div class="toolTitle">
#Model.ToolName;
</div>
<div class="toolThumb">
<img src=#Model.ToolThumbUrl alt=#Model.ToolThumbAlt>
</div>
<div class="toolDesc">
#Model.ToolDesc;
</div>
</td>
</tr>
}
</table>
</body>
</html>
I am using .Net v4.7.2 (I would be using 5.0.0 but none of my IDEs seem to want to use the newest version, I'm on a time crunch so can't spend ages debugging that so I'm just making do)
Cheers
I'm not entirely sure but the ; at the end of the line:
#model LgbtqWebsiteNoDb.Models.Tool;
in Tools/Index.cshtml might be messing it up
to me you missed Syntax error, '>' expected for img tag in file Tools/Index.cshtml

JavaScript isnt getting called before the Html

I have a script in my header that is calling a web api which should populate a view model. This is below.
#using GigHub.Controllers
#using GigHub.ViewModel
#model GigHub.ViewModel.ProjectsViewModel
#{
ViewBag.Title = "Projects";
}
<head>
<script>
(function getProjects() {
$.get("/api/projects")
.done(function () {
alert("Got Projects");
})
.fail(function () {
alert("Something failed!");
});
});
</script>
</head>
I then have my html that would loop through the viewModel and set it up throughout the html, but every time it gets run, it is throwing a null reference exception to Model.ProjectList in the for each because it hasn't populated yet. I thought putting the script in the header would let it run first, but that doesn't seem to be the case.
<h2>Projects</h2>
<ul class="gigs voffset4" style="width: 600px;">
#foreach (var project in Model.ProjectList)
{
<li>
<div class="date">
<div class="month">
#project.Name
</div>
<div class="day">
#project.Key
</div>
</div>
<div class="details">
<span class="artist">
#project.Id
</span>
<span class="genre">
#project.ProjectTypeKey
</span>
</div>
</li>
}
</ul>
Here is my actual projectsController
public class ProjectsController : Controller
{
private readonly string m_Username = Properties.Settings.Default.username;
private readonly string m_Password = Properties.Settings.Default.password;
public ActionResult Index()
{
var client = new RestClient("https://example.net/rest/api/2/");
client.Authenticator = new HttpBasicAuthenticator(m_Username, m_Password);
var request = new RestRequest("project/", Method.GET);
request.RequestFormat = DataFormat.Json;
request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; };
var response = client.Execute<List<Project>>(request);
var content = response.Content; // raw content as string
if (content == null)
throw new Exception(response.ErrorMessage);
var projectArray = JsonConvert.DeserializeObject<List<Project>>(response.Content);
var viewModel = new ProjectsViewModel()
{
ProjectList = projectArray,
Heading = "Projects"
};
return View("Projects", viewModel);
}
}
You are trying to mix javascript and C# code together and expecting it to work! No. It does not work that way.
The c# code in your view ( the foreach block) gets executed by razor in the server and the resulted html markup will be send to the client browser. That means, if you are accessing Model.ProjectList in your view, you should make sure that you are passing a model to your view with that property(ProjectList).
You have 2 options.
1. Full server side approach
In your get action, create an object of your view model, set the ProjectList property and send it to view.
public ActionResult Index()
{
var vm = new YourViewModel();
vm.ProjectList= GetListOfProjectsFromSomeWhere();
return View(vm);
}
private List<ProjectItem> GetListOfProjectsFromSomeWhere()
{
var list=new List<ProjectItem>();
list.Add(new ProjectItem { Name="Project 1"}); // Replace with real data here
return list;
}
Assuming you have a view model called YourViewModel as below
public class ProjectItem
{
public string Name {set;get;}
}
public class YourViewModel
{
public List<ProjectItem> ProjectList {set;get;}
}
and
and make sure your razor view is strongly typed to this view model
#model YourViewModel
<h2>Projects</h2>
#foreach (var project in Model.ProjectList)
{
<p>#project.Name</p>
}
2. Use ajax to load page content.
From your client side code,make the call to your api(like you did) and parse the response and update the DOM.
You need to create a container element in your view so that your javascript code can append items to that from the api call result.
<ul id="projects"></ul>
Now make sure that your javscript code will execute on the document ready event.
function getProjects() {
$.get("/api/projects")
.done(function (data) {
var projectHtml="";
$.each(data,function(i,item){
projectHtml+="<li>"+item.Name+"-"+item.Key+"</li>";
});
$("#projects").html(projectHtml);
})
.fail(function () {
alert("Something failed!");
});
}
$(function(){
getProjects();
});
Assuming your api call returns an array of item, each with a Name & Key property like this
[{Name:"Project1", Key:"Pr1"},{Name:"Project2", Key:"Pr2"}]

Using Jquery Globalize with MVC 5

I am trying to use the MVC unobstrusive validation with jquery globalize plugin in MVC5 (in conjunction with the package jquery-validate-globalize). For learning purposes I started a demo project as per here, but it fails to run with globalize (it works on default Microsoft unobstrusive validation). The model is very simple:
public class GlobalizeModel
{
[Range(10.5D, 20.3D)]
public decimal Double { get; set; }
[Required]
public DateTime? DateTime { get; set; }
}
I try to initiate Globalize as follows at the bottom of the _Layout page (the view is minimal with 2 input only): (I get list of necessary files from https://johnnyreilly.github.io/globalize-so-what-cha-want/)
<script src="~/Scripts/bootstrap.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<!--cldr scripts-->
<script src="~/Scripts/cldr.js"></script>
<script src="~/Scripts/cldr/event.js"></script>
<script src="~/Scripts/cldr/supplemental.js"></script>
<!--globalize scripts-->
<script src="~/Scripts/globalize.js"></script>
<script src="~/Scripts/globalize/number.js"></script>
<script src="~/Scripts/globalize/date.js"></script>
<!--jquery globalize-->
<script src="~/Scripts/jquery.validate.globalize.js"></script>
<script>
$.when(
$.getJSON("/Scripts/cldr/supplemental/likelySubtags.json"),
$.getJSON("/Scripts/cldr/main/en/numbers.json"),
$.getJSON("/Scripts/cldr/supplemental/numberingSystems.json"),
$.getJSON("/Scripts/cldr/main/en/ca-gregorian.json"),
$.getJSON("/Scripts/cldr/main/en/timeZoneNames.json"),
$.getJSON("/Scripts/cldr/supplemental/timeData.json"),
$.getJSON("/Scripts/cldr/supplemental/weekData.json"),
$.getJSON("/Scripts/cldr/main/tr/numbers.json"),
$.getJSON("/Scripts/cldr/main/tr/ca-gregorian.json"),
$.getJSON("/Scripts/cldr/main/tr/timeZoneNames.json"),
console.log("JSONs loaded")
).then(function () {
console.log("start slicing");
return [].slice.apply(arguments, [0]).map(function (result) {
console.log("slicing done");
return result[0];
});
}).then(Globalize.load).then(function () {
Globalize.locale("en");
console.log("Locale set to en");
}).then(console.log("LOADED EVERYTHING"));
</script>
But when I run the page, I only see the console logs JSOns loaded and LOADED EVERYTHING. Moreover, when I try a client side validation by typing anything in the number textbox (and of course when the focus is lost), I get the following error in the console:
Uncaught Error: E_DEFAULT_LOCALE_NOT_DEFINED: Default locale has not been defined.
This post here is similar, and I tried to check the things listed there. I think my JSON objects are not fetched, but I am not good aj JS so I am not sure on that. I added the following items to web.config to see if this is something related with file serving, with no avail:
<system.webServer>
<staticContent>
<remove fileExtension=".json"/>
<mimeMap fileExtension=".json" mimeType="application/json" />
</staticContent>
</system.webServer>
The culture is set to auto in web.config as follows:
<system.web>
<globalization culture="auto" uiCulture="auto" />
<compilation debug="true" targetFramework="4.5.2"/>
<httpRuntime targetFramework="4.5.2"/>
</system.web>
You can see Scripts folder structure in here:
So, what is the problem here? How can I make this thing work?
I recently ran into the same problem, trying to add I18n to an MVC5 web app. After several days of research and partly using your code as base, I found some things that helped me implement it.
My Solution:
In a separate project, I added decimal and DateTime properties to the ApplicationUser class:
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
public DateTime birthdate { get; set; }
public decimal balance { get; set; }
}
I also modified the RegisterViewModel to accept those properties, as follows:
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
[Required]
[DataType(DataType.DateTime)]
public DateTime birthdate { get; set; }
[Required]
[DataType(DataType.Currency)]
public decimal balance { get; set; }
}
Then, I set the culture in a base controller, from which other controllers inherit:
public class BaseController : Controller
{
protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state)
{
string[] cultures = { "es-CL", "es-GT", "en-US" };
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultures[1]);
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
return base.BeginExecuteCore(callback, state);
}
}
That's just for testing purposes, not the way I fetch culture in the real app.
My file structure is the same as yours and I didn't modify the web.config file.
I also used this link for dependencies. But then I modified a few things in the scripts section of Register.cshtml:
<!-- CLDR -->
<script src="~/Scripts/cldr.js"></script>
<script src="~/Scripts/cldr/event.js"></script>
<script src="~/Scripts/cldr/supplemental.js"></script>
<!-- Globalize -->
<script src="~/Scripts/globalize.js"></script>
<script src="~/Scripts/globalize/number.js"></script>
<script src="~/Scripts/globalize/date.js"></script>
<!-- $ validate -->
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.globalize.js"></script>
<!-- fetch files -->
<script>
$.when(
$.getJSON("/Scripts/cldr/supplemental/likelySubtags.json"),
$.getJSON("/Scripts/cldr/main/en/numbers.json"),
$.getJSON("/Scripts/cldr/supplemental/numberingSystems.json"),
$.getJSON("/Scripts/cldr/main/en/ca-gregorian.json"),
$.getJSON("/Scripts/cldr/main/en/timeZoneNames.json"),
$.getJSON("/Scripts/cldr/supplemental/timeData.json"),
$.getJSON("/Scripts/cldr/supplemental/weekData.json"),
$.getJSON("/Scripts/cldr/main/tr/numbers.json"),
$.getJSON("/Scripts/cldr/main/tr/ca-gregorian.json"),
$.getJSON("/Scripts/cldr/main/tr/timeZoneNames.json"),
).then(function () {
console.log("start slicing");
return [].slice.apply(arguments, [0]).map(function (result) {
console.log("slicing done");
return result[0];
});
}).then(Globalize.load).then(function () {
Globalize.locale("en");
console.log("Locale set to en");
}).then(console.log("LOADED EVERYTHING"));
</script>
The _Layout view scripts weren't modified at all, and I had no problem with the console logs.
That's all, it worked out for me, and as it's a very similar case, I hope it works for you too.

Razor in Javascript

I don't know how to use razor syntax in Javascript.
I want to make Html.ListBoxFor with items from my model. I used to use:
#Html.ListBoxFor(x => x.TagIdList, (MultiSelectList)ViewBag.Tags, new { #class = "chzn-select", data_placeholder = "Tags..." })
As you see I want also use chzn-select class, to have better layout.
For now, I just have this code above in HTML as plain text, but I want have there things from my model.
Any ideas?
There is my code in ASP.NET MVC:
#model Generator.Models.ExamModel
#{
ViewBag.Title = "Generate";
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script src="#Url.Content("~/Multiple_chosen/chosen.jquery.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/ListOfTags.js")" type="text/javascript"></script>
<script >
$(".chzn-select").chosen();
</script>
}
<link href="#Url.Content("~/Multiple_chosen/chosen.css")" rel="stylesheet" type="text/css" />
<h1>#ViewBag.Title</h1>
<h2>#ViewBag.Message</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Generate</legend>
<div class="editor-label">Numbers</div>
<div class="editor-field" id="NumberOfModels">
#Html.EditorFor(model => model.NumberOfQuestions)
</div>
<div class="editor-label">Tags</div>
<div id="itemsmodel"></div>
<br>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
And there is javascript file:
var models = document.getElementById("NumberOfQuestions");
var modelsTable = document.getElementById("itemsmodel");
models.addEventListener("change", drawModels, false);
function drawModels() {
var modelsNum = parseInt(models.value);
var curModels = modelsTable.childElementCount;
if (modelsNum > curModels) {
var delta = modelsNum - curModels;
for (var i = 0; i < delta; i++) {
var input = document.createElement("div");
input.className = "editor-field";
input.innerHTML = "#Html.ListBoxFor(x => x.TagIdList, (MultiSelectList)ViewBag.Tags, new { #class = \"chzn-select\", data_placeholder = \"Tags...\" })";
modelsTable.appendChild(input);
}
} else {
while (modelsTable.childElementCount > modelsNum) {
modelsTable.removeChild(modelsTable.lastChild);
}
}
}
drawModels();
My ViewModel: ExamModel.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ExamGenerator.Models
{
public class ExaminationModel
{
public int Id { get; set; }
public string Name { get; set; }
public List<int> TagIdList { get; set; }
public int NumberOfQuestions { get; set; }
public string Content { get; set; }
}
}
My ActionResult Generate() in controller:
public ActionResult Generate()
{
ViewBag.Tags = new MultiSelectList(genKolEnt.TAGS, "Id", "Name", null);
return View();
}
While you can generate HTML in Javascript using Razor, if the Javascript is in an MVC view, I find that injecting into JS leads to maintenance problems. You ideally want all your JS in separate files to allow for bundling/caching and the ability to break-point the JS code (which is harder in the view).
Either inject only simple things into JS on the page, or inject elements instead.
You can inject your template Razor list into a dummy script block, so you can extract the html from it later. The type="text/template" means the browser will ignore it e.g.:
<script id="ListTemplate" type="text/template">
#Html.ListBoxFor(x => x.TagIdList, (MultiSelectList)ViewBag.Tags, new { #class = "chzn-select", data_placeholder = "Tags..." })
</script>
The view page now looks like this (left out the irrelevant parts):
#section styles{
<link href="#Url.Content("~/Multiple_chosen/chosen.css")" rel="stylesheet" type="text/css" />
}
<h1>#ViewBag.Title</h1>
<h2>#ViewBag.Message</h2>
<script id="ListTemplate" type="text/template">
#Html.ListBoxFor(x => x.TagIdList, (MultiSelectList)ViewBag.Tags, new { #class = "chzn-select", data_placeholder = "Tags..." })
</script>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Generate</legend>
<div class="editor-label">Numbers</div>
<div class="editor-field" id="NumberOfModels">
#Html.EditorFor(model => model.NumberOfQuestions)
</div>
<div class="editor-label">Tags</div>
<div id="itemsmodel"></div>
<br>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
Script now looks like this (jQuery version with JS as comments):
// ListOfTags.js file
// This is a shortcut DOM ready handler for $(document).ready(function(){ YOUR CODE HERE })
$(function () {
// Attach an event handler for the "change" event
$('#NumberOfQuestions').change(function () {
var $numberOfQuestions = $(this); // Convert current DOM element (the counter) to a jQuery element
var $modelsTable = $('#itemsmodel'); // document.getElementById("itemsmodel");
var modelsNum = ~~$numberOfQuestions.val(); // parseInt(models.value);
var curModels = $modelsTable.children().length; // modelsTable.childElementCount
var delta = modelsNum - curModels;
// While too few, add more
while (delta > 0) {
var $input = $('<div>').addClass('editor-field'); // document.createElement("div"); .className = "editor-field";
var template = $('#ListTemplate').html(); // Fetch the template from a script block (id="ListTemplate")
$input.html(template); // input.innerHTML =
$modelsTable.append($input); // modelsTable.appendChild(input);
delta--;
}
// While too many, remove the last
while (delta++ < 0) {
$modelsTable.children().last().remove(); // modelsTable.removeChild(modelsTable.lastChild);
}
}).change(); // Trigger an initial change event so it runs immediately
});
Notes/tips:
Place any JS in the page, at the bottom of the view, as it is easier to find. It does not matter where the #section Scripts is as the master page determines where it is injected on the final page.
Always use single quotes (') in Javascript constants by default, so that nested strings can be " which are more often required than 's. Just a good habit to get into. In fact if you had used them your code may have worked as you have added \ escaping to the quotes which will mess up the Razor processing
e.g.:
= '#Html.ListBoxFor(x => x.TagIdList, (MultiSelectList)ViewBag.Tags, new { #class = "chzn-select", data_placeholder = "Tags..." })';
If you add a #RenderSection("styles", required: false) to your master page(s) you can do the same thing for CSS as you do for scripts (ensuring all CSS is loaded in the header (for consistency). Just place them in a #section styles block.
e.g.
<head>
...
#Styles.Render("~/Content/css")
#RenderSection("styles", required: false)
...
</head>
~~ is a handy (and fast) alternative to parseInt to convert values to integers.
Use $ as a prefix for jQuery object variables. This makes it easier to remember when to use jQuery methods vs DOM properties.
Test controller code:
private MultiSelectList TagList()
{
var items = new List<KeyValuePair<int, string>>() {
new KeyValuePair<int, string>(1, "MVC"),
new KeyValuePair<int, string>(2, "jQuery"),
new KeyValuePair<int, string>(3, "JS"),
new KeyValuePair<int, string>(4, "C#"),
new KeyValuePair<int, string>(5, "PHP")
};
MultiSelectList list = new MultiSelectList(items, "key", "value", null);
return list;
}
// Get request starts with one list
public ActionResult Test()
{
ExamModel vm = new ExamModel()
{
NumberOfQuestions = 1,
TagIdList = new List<int>()
};
ViewBag.Tags = TagList();
return View(vm);
}
[HttpPost]
public ActionResult Test(ExamModel model)
{
ViewBag.Tags = TagList();
return View(model);
}
If it's a static JavaScript file and you are not generating it dynamically with razor view engine It won't work because in this case there is no processing performed on a server side. It is the same as accessing static html page/css file/image and etc...
On the other hand if this JavaScript is part of some Razor view, which means that it gets rendered by razor view engine, when you have return View() (or anything like that) in your controller action, than this code should work.
The problem is, java script files are not processed by server, so you won't be able to insert anything in those using ASP.NET MVC. Razor files on the other hand are processed on server so you can insert data into those (either through view bag or model).
One way is:
.cshtml:
<script>
var someVariable = '#model.data';
</script>
then use this variable in your javascript file:
function someFunction(){
var myData = window.someVariable;
}
The other way is to have all javascript in .cshtml file and render it as a partial view.
#Html.Partial("Path/to/javascript/in/razor/view")
edit: seeing your code, this will not help you very much.
If you want to dynamically add/remove dom elements, you will have to do it with javascript: either generate them with "document.createElement()" or load them via ajax if you want some server side processing.
#Html.ListBoxFor
is a server side helper that generates tag and fills it up depending on the parameters. You can do that with javascript as well.

JavascriptResult puts javascript to the page as a string?

Iam a newbie of .NET MVC. I was trying to run all return types of MVC but I couldnt do work javascriptResult. The below is in my controller:
public ActionResult DoSomething() {
string s = "alert('Hello world!');";
return JavaScript(s);
}
This is in my view
#Ajax.ActionLink("click", "DoSomething", new AjaxOptions())
When I clicked the link, it puts "alert('Hello world!');" as a string and so not firing the alert. Whats wrong here ?
Seems that the documentation is "wrong" and the Controller.JavaScript action result is most likely only considered to return JavaScript include files (see also this thread):
Controller
public ActionResult JavaScript()
{
string s = "alert('Hello world!');";
return JavaScript(s);
}
View
<script type="text/javascript" src="~/Controller/JavaScript"></script>
If you want to return inline JavaScript you can use Controller.Content as your action result in combination with Html.RenderAction:
Controller
public ActionResult JavaScript()
{
string s = "alert('Hello world!');";
return Content(s);
}
View
<script type="text/javascript">
#{ Html.RenderAction("JavaScript", "Controller"); }
</script>

Categories

Resources