It appears that after solving my previous issue with CSS, I've come into another roadblock. I was trying to do the "Optimization: Server-side rendering" exercise from the reactjs.net website. Unfortunately, problem - I can't use the "#Html.React" method in the razor view to pass the Comment Box model. I've tried several what were probably unnecessary imports, and ensuring that my ReactConfig file was updated so that I could use that code. Can anyone tell me what I'm missing here?
ReactConfig.cs:
using React;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(ReactExamplePractice.ReactConfig), "Configure")]
namespace ReactExamplePractice
{
using React;
public static class ReactConfig
{
public static void Configure()
{
// If you want to use server-side rendering of React components,
// add all the necessary JavaScript files here. This includes
// your components as well as all of their dependencies.
// See http://reactjs.net/ for more information. Example:
//ReactSiteConfiguration.Configuration
// .AddScript("~/Scripts/First.jsx")
// .AddScript("~/Scripts/Second.jsx");
ReactSiteConfiguration.Configuration = new ReactSiteConfiguration()
.AddScript("~/Scripts/react/Tutorial.jsx");
//ReactSiteConfiguration.Configuration
// //.AddScript("~/js/remarkable.min.js")
// .AddScript("~/Scripts/react/Tutorial.jsx");
// If you use an external build too (for example, Babel, Webpack,
// Browserify or Gulp), you can improve performance by disabling
// ReactJS.NET's version of Babel and loading the pre-transpiled
// scripts. Example:
//ReactSiteConfiguration.Configuration
// .SetLoadBabel(false)
// .AddScriptWithoutTransform("~/Scripts/bundle.server.js")
}
}
}
BundleConfig.cs:
using System.Web;
using System.Web.Optimization;
using System.Web.Optimization.React;
namespace ReactExamplePractice
{
public class BundleConfig
{
// For more information on bundling, visit https://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 BabelBundle("~/bundles/main").Include(
"~/Scripts/react/Tutorial.jsx"
));
// Forces files to be combined and minified in debug mode
// Only used here to demonstrate how combination/minification works
// Normally you would use unminified versions in debug mode.
BundleTable.EnableOptimizations = true;
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 https://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"));
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/site.css"));
}
}
}
_Layout.cshtml:
#using System.Web.Optimization.React;
#using React;
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
#*<environment exclude="Development">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
</environment>*#
<environment exclude="Development">
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
</environment>
<title>#ViewData["Title"] - ASP.NET Core Pages Webpack</title>
#model IEnumerable<ReactExamplePractice.Models.CommentModel>
#{
Layout = null;
}
</head>
<body>
<div class="container">
<nav class="bg-dark mb-4 navbar navbar-dark navbar-expand-md">
<a asp-page="/Index" class="navbar-brand">
<em>ASP.NET Core Pages Webpack</em>
</a>
<button aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation" class="navbar-toggler" data-target="#topNavbarCollapse" data-toggle="collapse" type="button">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="topNavbarCollapse">
<ul class="mr-auto navbar-nav">
<li class="nav-item">
#Html.ActionLink("Application Name", "Index", "Default", new { area = "" }, new { #class = "navbar-brand" })
</li>
<li class="nav-item">
<a asp-page="/About" class="nav-link">About</a>
</li>
<li class="nav-item">
<a asp-page="/Contact" class="nav-link">Contact</a>
</li>
</ul>
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="https://twitter.com/damien_bod">
<img height="30" src="assets/damienbod.jpg" />
</a>
</li>
</ul>
</div>
</nav>
</div>
<partial name="_CookieConsentPartial" />
<div class="container body-content">
#RenderBody()
<hr />
<footer>
<p>© 2018 - ASP.NET Core Pages Webpack Bootstrap 4</p>
</footer>
</div>
<environment exclude="Development">
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
#*<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js" integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T" crossorigin="anonymous"></script>*#
<script src="~/Scripts/jquery-3.3.1.slim.min.js"></script>
<script src="~/Scripts/popper.min.js"></script>
<script src="~/Scripts/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.7.1/remarkable.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.js"></script>
#Scripts.Render("~/bundles/main");
#*<script src="#Url.Content("~/Scripts/react/Tutorial.jsx")"></script>*#
</environment>
#RenderSection("Scripts", required: false)
</body>
</html>
DefaultController.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.UI;
using ReactExamplePractice.Models;
using System.Web.Optimization.React;
using React;
namespace ReactExamplePractice.Controllers
{
public class DefaultController : Controller
{
private static readonly IList<CommentModel> _comments;
static DefaultController()
{
_comments = new List<CommentModel>
{
new CommentModel
{
Id = 1,
Author = "Daniel Lo Nigro",
Text = "Hello ReactJS.NET World!"
},
new CommentModel
{
Id = 2,
Author = "Pete Hunt",
Text = "This is one comment"
},
new CommentModel
{
Id = 3,
Author = "Jordan Walke",
Text = "This is *another* comment"
},
};
}
[OutputCache(Location = OutputCacheLocation.None)]
public ActionResult Comments()
{
return Json(_comments, JsonRequestBehavior.AllowGet);
}
[HttpPost]
public ActionResult AddComment(CommentModel comment)
{
//Create a fake ID for this comment or something
comment.Id = _comments.Count + 1;
_comments.Add(comment);
return Content("Success :)");
}
// GET: Default
public ActionResult Index()
{
return View();
}
}
}
Tutorial.jsx:
class CommentBox extends React.Component {
constructor(props) {
super(props);
this.state = { data: this.props.initialData };
this.handleCommentSubmit = this.handleCommentSubmit.bind(this);
}
loadCommentsFromServer() {
const xhr = new XMLHttpRequest();
xhr.open('get', this.props.url, true);
xhr.onload = () => {
const data = JSON.parse(xhr.responseText);
this.setState({ data: data });
};
xhr.send();
}
handleCommentSubmit(comment) {
const comments = this.state.data;
// Optimistically set an id on the new comment. It will be replaced by an
// use a more robust system for ID generation.
// id generated by the server. In a production application you would likely
comment.Id = comments.length + 1;
const newComments = comments.concat([comment]);
this.setState({data: newComments});
const data = new FormData();
data.append('Author', comment.Author);
data.append('Text', comment.Text);
const xhr = new XMLHttpRequest();
xhr.open('post', this.props.submitUrl, true);
xhr.onload = () => this.loadCommentsFromServer();
xhr.send(data);
}
componentDidMount() {
window.setInterval(() => this.loadCommentsFromServer(), this.props.pollInterval);
}
render() {
return (
<div className="commentBox">
<h1>Comments</h1>
<CommentList data={this.state.data} />
<CommentForm onCommentSubmit={this.handleCommentSubmit} />
</div>
);
}
}
class CommentList extends React.Component {
render() {
const commentNodes = this.props.data.map(comment => (
<Comment author={comment.Author} key={comment.Id}>
{comment.Text}
</Comment>
));
return (
<div className="commentList">
{commentNodes}
</div>
);
}
}
class CommentForm extends React.Component {
constructor(props) {
super(props);
this.state = { author: '', text: '' };
this.handleAuthorChange = this.handleAuthorChange.bind(this);
this.handleTextChange = this.handleTextChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleAuthorChange(e) {
this.setState({author: e.target.value});
}
handleTextChange(e) {
this.setState({ text: e.target.value });
}
handleSubmit(e) {
e.preventDefault();
const author = this.state.author.trim();
const text = this.state.text.trim();
if (!text || !author) {
return;
}
this.props.onCommentSubmit({Author: author, Text: text});
this.setState({ author: '', text: '' });
}
render() {
return (
<form className="commentForm" onSubmit={this.handleSubmit} >
<input type="text" placeholder="Your name" value={this.state.author} onChange={this.handleAuthorChange} />
<input type="text" placeholder="Post something here!" value={this.state.text} onChange={this.handleTextChange} />
<input type="submit" value="Post" />
</form>
);
}
}
class Comment extends React.Component {
rawMarkup() {
const md = new (global.Remarkable || window.Remarkable)();
const rawMarkup = md.render(this.props.children.toString());
return { __html: rawMarkup };
}
render() {
return (
<div className="comment">
<h2 className="commentAuthor">
{this.props.author}
</h2>
<span dangerouslySetInnerHTML={this.rawMarkup()} />
</div>
);
}
}
class HelloWorld extends React.Component {
render() {
return (
<div>
<h1> Hello World React JS! </h1>
</div>)
}
}
//ReactDOM.render(
// <CommentBox url="/comments" submitUrl="/comments/new" pollInterval={2000} />,
// document.getElementById('content')
//);
Any help/insight on this would be greatly appreciated. Thanks a ton in advance!
So, I've come to discover something odd, and maybe it's just my Visual Studio environment or something else, but when using the Html.React library from the NuGet package, it would fail to load the methods at first - but then, as soon as I saved the project, exited, and opened back up, this intellisense glitch disappeared!
I also want to mention quickly that there is a bug in the Remarkable library in the ASP.NET tutorial online. See the following post:
https://github.com/reactjs/React.NET/issues/349
I believe there is a workaround in there for this bug as well, whoever needs it.
This scenario was a strange one. I hope this post helps someone else down the road.
Related
I followed the solution for using Carousel with Blazor, but get Object exception when I run the app.
How to use Bootstrap Carousel in Blazor
_Host.cshtml:
<body>
<app>#(await Html.RenderComponentAsync<App>())</app>
<script src="_framework/blazor.server.js"></script>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"></script>
#*<script src="_framework/blazor.webassembly.js"></script>*#
<script>
window.initializeCarousel = () => {
$('#mycarousel').carousel({ interval: 2000 });
//see step 2 to understand these news id's:
$('#mycarousel-prev').click(
() => $('#mycarousel').carousel('prev'));
$('#mycarousel-next').click(
() => $('#mycarousel').carousel('next'));
}
</script>
</body>
</html>
Razor Page:
#page "/fullDetails/{id:int}"
#using BlazorApp2.Data
#using System.Collections.Generic
#inject IJSRuntime JsRuntime;
#inject VehicleService VService
#inherits UIAttributes
<h1>Vehicle Details</h1>
<hr />
<div>
#if (vehicleInfo == null)
{
<p><em>Loading...</em></p>
}
else
{
<div class="col-lg-4 col-md-6 col-sm-6">
<div id="mycarousel" class="carousel slide" data-ride="carousel">
<div class="carousel-inner">
#foreach (var img in images)
{
if (img.SeqNo == "1")
{
<div class="carousel-item active">
<img class="d-block w-100" src="/images/#img.ImageName" alt="None">
</div>
}
else
{
<div class="carousel-item">
<img class="d-block w-100" src="/images/#img.ImageName" alt="None">
</div>
}
}
</div>
<!-- Left and right controls -->
<a class="carousel-control-prev" id="mycarousel-prev" data-slide="prev">
<span class="carousel-control-prev-icon"></span>
</a>
<a class="carousel-control-next" id="mycarousel-next" data-slide="next">
<span class="carousel-control-next-icon"></span>
</a>
</div>
</div>
</div>
#*If using #code per new speck you get errors when using this type of format await _jsRuntime.InvokeAsync<object>("initializeCarousel"); -- where <object> while be seen as markup 08/06/2019*#
#functions{
VehicleFullDetails vehicleInfo;
VehicleImage[] images;
string first { get; set; }
[Parameter]
int id { get; set; }
protected override async Task OnInitAsync()
{
vehicleInfo = await VService.OnGetVehicleFullDetailsAsync(id);
images = vehicleInfo.Images.ToArray();
}
private IJSRuntime _jsRuntime;
bool firstRender = true;
protected async override Task OnAfterRenderAsync()
{
if (firstRender)
{
(line 107) await _jsRuntime.InvokeAsync<object>("initializeCarousel");
firstRender = false;
}
}
}
[2019-08-07T15:51:05.848Z] Error: System.AggregateException: One or more errors occurred. (Object reference not set to an instance of an object.)
---> System.NullReferenceException: Object reference not set to an instance of an object.
at BlazorApp2.Pages.FullDetails.OnAfterRenderAsync() in C:\projects\blazor\gettingStarted\BlazorApp2\BlazorApp2\Pages\FullDetails.razor:line 107
--- End of inner exception stack trace ---
JavaScript doesn't work with Blazor in a way it worked with default Razor pages earlier, Because Server-side Blazor uses WebAssembly and transfers data to user in binary format.
And when <script> transferred in parts it can't run.
There is two way of solving your problem:
1) - one is change Blazor from Server side to Client Side (so user downloads full page with all scripts)
2) - second is to use JavaScript interop how to use it you can read in official MS documentation ASP.NET Core Blazor JavaScript interop
You also have some syntax errors, in your code:
await _jsRuntime.InvokeAsync<object>("initializeCarousel");
But you referring to JS script so it should be js file like this:
await _jsRuntime.InvokeAsync<object>("initializeCarousel.js");
I placed the script into a initCarousel.js file and added it to _host.cshtml page. I then modified my #function code to:
bool firstRender = true;
protected async override Task OnAfterRenderAsync()
{
if (firstRender)
{
await jsRuntime.InvokeAsync<string>("initializeCarousel");
firstRender = false;
}
}
The server-side application now cycles through the images and allow next/prev selection.
Thanks to Chris Sainty for the clarification: https://chrissainty.com/using-javascript-interop-in-razor-components-and-blazor/
I want to create an application that can notify the users while anything is inserted/updated or deleted in the database.
I have used Signalr along with sql dependancy, but still don't get any notification while a change occurs in database.
This is the controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public JsonResult GetNotificationContacts()
{
var notificationRegisterTime = Session["LastUpdated"] != null ? Convert.ToDateTime(Session["LastUpdated"]) : DateTime.Now;
NotificationComponent NC = new NotificationComponent();
var list = NC.GetContacts(notificationRegisterTime);
//update session here for get only new added contacts (notification)
Session["LastUpdate"] = DateTime.Now;
return new JsonResult { Data = list, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
}
This is the startup.Cs class
namespace PushNotification
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
This is the connection string in web.config file
<connectionStrings>
<add name="sqlConString" connectionString="data source=SHOAIB\SQLEXPRESS;initial catalog=MyPushNotification;integrated security=True;" />
<add name="MyPushNotificationEntities2" connectionString="metadata=res://*/MyPushNotificationModel.csdl|res://*/MyPushNotificationModel.ssdl|res://*/MyPushNotificationModel.msl;provider=System.Data.SqlClient;provider connection string="data source=shoaib\sqlexpress;initial catalog=MyPushNotification;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
This is the Hub named as NotificationHub in my application
namespace PushNotification
{
public class NotificationHub : Hub
{
//public void Hello()
//{
// Clients.All.hello();
//}
}
}
This is the notification component class
namespace PushNotification
{
public class NotificationComponent
{
//Here we will add a function for register notification (will add sql dependency)
public void RegisterNotification(DateTime currentTime)
{
string conStr = ConfigurationManager.ConnectionStrings["sqlConString"].ConnectionString;
string sqlCommand = #"SELECT [ContactId],[ContactName],[ContactNo] from [dbo].[Contacts] where [AddedOn] > #AddedOn";
//you can notice here I have added table name like this [dbo].[Contacts] with [dbo], its mendatory when you use Sql Dependency
using (SqlConnection con = new SqlConnection(conStr))
{
SqlCommand cmd = new SqlCommand(sqlCommand, con);
cmd.Parameters.AddWithValue("#AddedOn", currentTime);
if (con.State != System.Data.ConnectionState.Open)
{
con.Open();
}
cmd.Notification = null;
SqlDependency sqlDep = new SqlDependency(cmd);
sqlDep.OnChange += sqlDep_OnChange;
//we must have to execute the command here
using (SqlDataReader reader = cmd.ExecuteReader())
{
// nothing need to add here now
}
}
}
void sqlDep_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
SqlDependency sqlDep = sender as SqlDependency;
sqlDep.OnChange -= sqlDep_OnChange;
//from here we will send notification message to client
var notificationHub = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
notificationHub.Clients.All.notify("added");
//re-register notification
RegisterNotification(DateTime.Now);
}
}
public List<Contact> GetContacts(DateTime afterDate)
{
using (MyPushNotificationEntities2 dc = new MyPushNotificationEntities2())
{
return dc.Contacts.Where(a => a.AddedOn > afterDate).OrderByDescending(a => a.AddedOn).ToList();
}
}
}
}
I made changes in global.asax file as below
namespace PushNotification
{
public class MvcApplication : System.Web.HttpApplication
{
string con = ConfigurationManager.ConnectionStrings["sqlConString"].ConnectionString;
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
//here in Application Start we will start Sql Dependency
SqlDependency.Start(con);
}
protected void Session_Start(object sender, EventArgs e)
{
NotificationComponent NC = new NotificationComponent();
var currentTime = DateTime.Now;
HttpContext.Current.Session["LastUpdated"] = currentTime;
NC.RegisterNotification(currentTime);
}
protected void Application_End()
{
//here we will stop Sql Dependency
SqlDependency.Stop(con);
}
}
}
And finally this is the _layout file along with the changes
<!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>
<link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
<script src="~/Scripts/modernizr-2.6.2.js"></script>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<span class="noti glyphicon glyphicon-bell"><span class="count"> </span></span>
<div class="noti-content">
<div class="noti-top-arrow"></div>
<ul id="notiContent"></ul>
</div>
<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", null, new { #class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
</ul>
</div>
</div>
</div>
<div class="container body-content">
#RenderBody()
<hr />
<footer>
<p>© #DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
#* Add Jquery Library *#
<script src="~/Scripts/jquery-2.2.3.min.js"></script>
<script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
<script src="/signalr/hubs"></script>
<script src="~/Scripts/bootstrap.min.js"></script>
#* Add css *#
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
<style type="text/css">
/*Added css for design notification area, you can design by your self*/
/* COPY css content from youtube video description*/
.noti-content{
position:fixed;
right:100px;
background:#e5e5e5;
border-radius:4px;
top:47px;
width:250px;
display:none;
border: 1px solid #9E988B;
}
ul#notiContent{
max-height:200px;
overflow:auto;
padding:0px;
margin:0px;
padding-left:20px;
}
ul#notiContent li {
margin:3px;
padding:6px;
background:#fff;
}
.noti-top-arrow{
border-color:transparent;
border-bottom-color:#F5DEB3;
border-style:dashed dashed solid;
border-width: 0 8.5px 8.5px;
position:absolute;
right:32px;
top:-8px;
}
span.noti{
color:#FF2323;
margin:15px;
position:fixed;
right:100px;
font-size:18px;
cursor:pointer;
}
span.count{
position:relative;
top:-3px;
}
</style>
#* Add jquery code for Get Notification & setup signalr *#
<script type="text/javascript">
$(function () {
// Click on notification icon for show notification
$('span.noti').click(function (e) {
e.stopPropagation();
$('.noti-content').show();
var count = 0;
count = parseInt($('span.count').html()) || 0;
//only load notification if not already loaded
if (count > 0) {
updateNotification();
}
$('span.count', this).html(' ');
})
// hide notifications
$('html').click(function () {
$('.noti-content').hide();
})
// update notification
function updateNotification() {
$('#notiContent').empty();
$('#notiContent').append($('<li>Loading...</li>'));
$.ajax({
type: 'GET',
url: '/home/GetNotificationContacts',
success: function (response) {
$('#notiContent').empty();
if (response.length == 0) {
$('#notiContent').append($('<li>No data available</li>'));
}
$.each(response, function (index, value) {
$('#notiContent').append($('<li>New contact : ' + value.ContactName + ' (' + value.ContactNo + ') added</li>'));
});
},
error: function (error) {
console.log(error);
}
})
}
// update notification count
function updateNotificationCount() {
var count = 0;
count = parseInt($('span.count').html()) || 0;
count++;
$('span.count').html(count);
}
// signalr js code for start hub and send receive notification
var notificationHub = $.connection.notificationHub;
$.connection.hub.start().done(function () {
console.log('Notification hub started');
});
//signalr method for push server message to client
notificationHub.client.notify = function (message) {
if (message && message.toLowerCase() == "added") {
updateNotificationCount();
}
}
})
</script>
</body>
</html>
My database is in sql server management studio, when i insert a new record, i dont get any notification in the front end.
Please help if you have expertise in this regard.
Many thanks in advance.
you have to open service broker
ALTER DATABASE [yourdatabasename] SET ENABLE_BROKER WITH ROLLBACK IMMEDIATE ;
I am trying to make a simple HTTP:GET request using Unity to a local NodeJs Server.
My network is protected by proxy but, in this case, I am requesting to localhost.
By the way, the request works if I test it on browser or Postman.
I believe that maybe it is something related to the headers. From UnityWebRequest.SetRequestHeader documentation:
These headers cannot be set with custom values on any platform: accept-charset, access-control-request-headers, access-control-request-method, connection, date, dnt, expect, host, keep-alive, origin, referer, te, trailer, transfer-encoding, upgrade, via.
What I don't understand is why it is hitting the proxy?
Below are the scripts I used and the response.
NodeJs server
const express = require('express');
const app = express();
app.get('/', function(req, res) {
console.log('test');
return res.sendStatus(200);
})
app.listen(8080, () => {
console.log(`Magic happens on port 8080`);
});
module.exports = app;
Unity Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class Request : MonoBehaviour
{
private GUIStyle guiStyle = new GUIStyle ();
string uri = "http://127.0.0.1:8080";
void Start ()
{
Get();
}
void Update ()
{
}
public void Get ()
{
StartCoroutine (SendGet ());
}
IEnumerator SendGet ()
{
Debug.Log (uri);
using (UnityWebRequest www = UnityWebRequest.Get (uri)) {
yield return www.Send ();
if (www.isError) {
Debug.Log (www.error);
} else {
Debug.Log (www.downloadHandler.text);
byte[] results = www.downloadHandler.data;
Debug.Log (results);
}
}
}
}
Output
<!DOCTYPE html>
<!--
Message.TemplateName: authenticationrequired
Message.Language: Fallback
-->
<html>
<!-- head -->
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
<title>McAfee Web Gateway - Notification - Authentication Required</title>
<script src="/mwg-internal/de5fs23hu73ds/files/javascript/sw.js" type="text/javascript" ></script>
<link rel="stylesheet" type="text/css" href="/mwg-internal/de5fs23hu73ds/files/system/stylesheet.css" />
</head>
<!-- /head -->
<!-- body -->
<body onload="swOnLoad();" style="background-image: url('/mwg-internal/de5fs23hu73ds/files/system/img/bg_body.jpg');">
<!-- wrapper -->
<div class="wrapper">
<!-- maincontent -->
<div class="maincontent" style="background-image: url('/mwg-internal/de5fs23hu73ds/files/system/img/bg_container.png');">
<div class="header" id="header" style="background-image: url('/mwg-internal/de5fs23hu73ds/files/system/img/bg_navbar.png');">
Authentication Required
</div>
<!-- content -->
<div class="content">
You must be authenticated to access this URL.<br/>
<div class="info">
<!-- Client IP -->
<b>Client IP:</b> 10.0.20.188
<br/>
<!-- URL -->
<b>URL:</b> <script type="text/javascript">break_line("http://localhost:8080");</script>
<br/>
</div>
</div>
<!-- /content -->
<!-- action -->
<!-- spacer --><div style="height: 10px;"></div><!-- /spacer -->
<div class="action">
<form name="ftpform" method="get" action="" id="ftpform" style="display:none;">
<table>
<tr><td><b>FTP User Name:</b></td><td><input type="text" name="ftpUsername" id="ftpUsername" /></td></tr>
<tr><td><b>FTP Password:</b></td><td><input type="password" name="ftpPassword" id="ftpPassword" /></td></tr>
<tr><td><b>Please confirm:</b></td><td><input type="button" value="Access FTP" onClick="redirectToFTP();" /></td></tr>
</table>
</form>
</div>
<script language="javascript" type="text/javascript">
urlprotocol = "http";
statuscode=407;
if(statuscode==401 && urlprotocol == "ftp"){
document.getElementById("ftpform").style.display = "block";
}
function redirectToFTP(){
var username=escape(document.getElementById("ftpUsername").value);
var password=escape(document.getElementById("ftpPassword").value);
location.href = "ftp://"+username+":"+password+"#localhost:8080"
}
</script>
<!-- /action -->
<!-- footer -->
<div class="footer">
generated 2018-03-20 08:28:01
by MWGBP01 <span class="notdisplayfalse">(10.0.1.186:8080)</span><br/>
Autenticação: Active Directory(Autenticação: Proxy explícito)
</div>
<!-- /footer -->
</div>
<!-- /maincontent -->
</div>
<!-- /wrapper -->
</body>
<!-- /body -->
</html>
UnityEngine.Debug:Log(Object)
<SendGet>c__Iterator0:MoveNext() (at Assets/Scripts/Request.cs:39)
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
There are two pages: Login.aspx and Profile.aspx, which are built using HTML and AngularJS.
The login.aspx page uses ng-view to get the template of Login-view or Signup View.
The code used is:
<head>
<title></title>
<base href="/Login.aspx" />
<link href="StyleSheet/Login_css.css" rel="stylesheet" />
<script src="JscriptVendors/angular.min.js"></script>
</head>
<body ng-app="JouralApp_login">
<div ng-view></div>
<script src="Jscript_Angular/Model.js"></script>
<script src="Jscript_Angular/Controllers/LoginPageController.js"></script>
<script src="JscriptVendors/angular-route.min.js"></script>
<script src="JscriptVendors/angular-animate.min.js"></script>
<script src="JscriptVendors/jquery.min.js"></script>
</body>
The views are stored in Template folder with the names as: loginTemplate.html, and signupTemplate.html.
The module used for handling the login.aspx page is:
var app_login = angular.module('JouralApp_login', ['ngRoute','ngAnimate']);
var app_profile = angular.module('GameApp', []);
app_login.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$routeProvider
.when('/login', {
templateUrl: 'Jscript_Angular/Templates/loginTemplate.html',
controller: 'loginController'
})
.when('/signup', {
templateUrl: 'Jscript_Angular/Templates/signupTemplate.html'
}).otherwise({
redirectTo:'/login'
})
}]);
Now a created my Profile.aspx, with the HTML code as:
<head>
<script src="Scripts/angular.js"></script>
</head>
<body ng-app="app_profile">
<div ng-controller="chatController">
<div>
<div ng-repeat="chat in messages">{{chat}}</div>
<div>
<input type="text ng-model="message" />
<input type="button" ng-click="newMessage()" />
</div>
</div>
</div>
<script src="Jscript_Angular/Model.js"></script>
<script src="Scripts/jquery-1.6.4.js"></script>
<script src="Scripts/jquery.signalR-2.2.0.js"></script>
<script src="signalr/hub"></script>
<script src="Jscript_Angular/Controllers/ChatController.js"></script>
</body>
Every thing was working fine until I try to integrate SignalR into my project.
I made two classes:
CLASS 1:
[assembly: OwinStartup(typeof(Startup))]
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
CLASS 2:
public class ChatHub : Hub
{
public void SendMessage(string name, string message)
{
Clients.All.broadcastMessage(name, message);
}
}
I also made the following controller in order to access my javascript function:
app_profile.controller('chatController',['$scope', function ($scope) {
$scope.name = 'Guest';
$scope.message = '';
$scope.messages = [];
$scope.chatHub = null;
$scope.chatHub = $.connection.chatHub;
$.connection.hub.start();
$scope.chatHub.client.broadcastMessage = function (name, message) {
var newMessage = name + " " + message;
$scope.messages.push(newMessage);
$scope.$apply();
};
$scope.newMessage = function () {
$scope.chatHub.server.sendMessage($scope.name, $scope.message);
$scope.message = '';
}
}]);
Now when I try to access my profile page, it show the error
angular.js:13550 Error: SignalR: Error loading hubs. Ensure your hubs reference is correct, e.g. .
Also when i try to access, localhost:5136/signalr/hubs, it redirects me to my login page, i.e: localhost:5136/login
I think the problem is that, it cannot access the hub which I created because of the routing which i did using angularJS for the login page.
Please help me find the solution.
I am really new to MVC and C#
I modified the _Layout.cshtml to have a menu and on click of any menu item I have a jquery function to create sub menu items based on the parent that I clicked. When I click on any link in the sub menu It reloads the master page and clears my sub menu which is something I don't like. Can someone help me recreate dynamically the same sub menu after page reload or any idea to fix that issue is welcome
OK
I created a controller that I am accessing in my _Layout to create my menu bar
public abstract class MainController : Controller
{
private static HRMenuDataContext db = new HRMenuDataContext();
public static string theVal, toCheck;
public static int num;
public static HRMenuDataContext theData
{
get { return db; }
}
public MainController()
{
//ViewData["Parent"] = from c in theData.psHCMLanguages
// where
// (from m in theData.psHCMMenus
// where
// m.sModule == "AP"
// select m.sMainRef
// ).Distinct().Contains(c.szCode)
// select c;
ViewData["parent"] = theData.theParent("HR");
ViewData["check"] = theData.doCheck(toCheck);
ViewData["Child"] = from c in theData.psHCMLanguages
where
(from m in theData.psHCMMenu_1s
let parent = theVal
where
m.sModule == "HR" &&
m.sSubRef == parent
select
m.sPrompt
).Contains(c.szCode)
select c;
}
}
in my _Layout.cshtml I have this
#using Menus.Data;
#using Menus.Controllers;
#using System.Linq;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>#ViewBag.Title - Persol Systems</title>
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<meta name="viewport" content="width=device-width" />
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
<link href="~/Content/theStyle.css" rel="stylesheet" />
<style type="text/css">
#theSide {
clear:both;
position:relative;
float:left;
left:100px;
bottom:50px;
top:0;
border:1px solid red;
width:150px;
height:600px;
}
</style>
</head>
<body>
#{
string[] name;
char[] sep = { ' ', '/', '\\', '.' };
string mess="";
}
<header>
<div class="content-wrapper">
<div class="float-left">
<p class="site-title">#Html.ActionLink("your logo here", "Index", "Home")</p>
</div>
<div class="float-right">
<section id="login">
#Html.Partial("_LoginPartial")
</section>
<nav>
<ul id="menux">
#{
foreach (var c in (IEnumerable<theParentResult>)ViewData["parent"])
{
<li><a>#c.English </a>
#{MainController.theVal = c.szCode;}
<ul class="firstChild">
#{foreach (var d in (IEnumerable<psHCMLanguage>)ViewData["Child"])
{
var data = MainController.theData.doCheck(d.szCode);
if ((int)data == 1)
{
<li><a onclick="theAlert('#d.szCode','#d.English')">#d.English</a>
#{
MainController.theVal = d.szCode;
}
</li>
}
else if (data == 0)
{
name = d.English.Split(sep);
foreach (string nams in name)
{
mess += nams;
}
<li>
<a onclick="theAlert('#d.szCode','#d.English')">#d.English</a>
#*#Html.ActionLink(d.English, mess, c.English)*#
</li>
mess = "";
Array.Clear(name, 0, name.Length);
}
}
}
</ul>
</li>
}
}
</ul>
</nav>
</div>
</div>
</header>
<div id="body">
<div id="theSide">
<ul id="sidePanel">
</ul>
</div>
#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 - Persol Systems</p>
</div>
</div>
</footer>
#Scripts.Render("~/bundles/jquery")
#RenderSection("scripts", required: false)
<script type="text/javascript">
function theAlert(theId, theName) {
$("ul#sidePanel").contents().remove();
$("ul#sidePanel ").append("<li id='" + theId + "'><a >" + theId + "</a></li>");
$("li#" + theId + "> a").click(function (e) {
window.location.href("../Home/About");
});
return false;
}
</script>
</body>
</html>
on click of the link It reloads the entire page and clears my sidePanel
HTTP is stateless which means any data that you do not persist will get lost between postbacks. If you want to persist that information you will need to use Javascript to send the menu structure to the server through Ajax or use browser based local storage.
An example scenerio
model
public class Menu
{
// prop parent for example
public List<Parents> parents{ get; set; }
// prop child
public List<Childs> child{ get; set; }
// prop check
public bool checked { get; set; }
}
controller
public class Menu: Controller
{
public ActionResult _MainMenu()
{
Menu menu = new Menu();
menu.Parent = // parent elements from your db context
menu.Child = // child elements from your db context
menu.Parent = // check element from your db context
return PartialView(menu);
}
}
_MainMenu.cshtml
#model Menu
// same like your layout view, fill here like layout
// for example
#foreach(var parent in Model.Parents)
{
// generate menus
....
}
_Layout.cshtml
...
<nav>
<ul id="menux">
#Html.Action("_MainMenu", "Menu")
</ul>
</nav>
...
I suggest you an example code you should modify Data Types that you want.