I want to make a feed application using SSE in MVC .NET. I was looking over the web but I can't find an example or a way to implement the SSE in MVC. I developed a very dirty solution where a View calls a Controller that calls a second View, and this 2nd View makes the push to the first one. I hope that somebody can help. Thanks.
Take a look at SignalR. It is very easy to set up and get running, and there are plenty of examples in ASP.NET to get you started.
If ASP.NET WebApi is an option you can checkout my library, ServerSentEvents4Net. The code is up on Github, and its also available on Nuget.
Here's an example to implement sse in mvc4 using .net (it should work fine for MVC3 also)
Controller part:
public ActionResult Index()
{
ViewBag.Message = "SSE WITH ASP.NET MVC";
return View();
}
public ActionResult Message()
{
var result = string.Empty;
var sb = new StringBuilder();
sb.AppendFormat("data: {0}\n\n", DateTime.Now.ToString());
return Content(sb.ToString(), "text/event-stream");
}
View Part:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script type="text/javascript">
function contentLoaded() {
var source = new EventSource('home/message');
//var ul = $("#messages");
source.onmessage = function (e) {
var li = document.createElement("li");
var returnedItem = e.data;
li.textContent = returnedItem;
$("#messages").append(li);
}
};
window.addEventListener("DOMContentLoaded", contentLoaded, false);
</script>
<h2><%: ViewBag.Message%></h2>
<p>
SSE WITH ASP.NET MVC
</p>
<ul id="messages">
</ul>
Output:
Related
Is it possible to refresh a View Component in an ASP.NET Core 2.1 Razor page?
I discovered that this is possible in ASP.NET MVC using AJAX—see solutions at Viewcomponent alternative for ajax refresh and ViewComponents are not async. But what about ASP.NET Core?
One solution I found is basically to have a controller returning the View Component, and then using AJAX to do the refresh.
This is example is borrowed from ViewComponents are not async
~/HelloWorldViewComponent.cs
public class HelloWorldViewComponent : ViewComponent
{
public IViewComponentResult Invoke()
{
var model = new string[]
{
"Hello", "from", "the", "view", "component."
};
return View("Default", model);
}
}
~/HomeController.cs (I cannot get this part working in razor pages)
public class HomeController : Controller
{
public IActionResult GetHelloWorld()
{
return ViewComponent("HelloWorld");
}
}
~/Views/Shared/Components/HelloWorld/Default.cshtml
#model string[]
<ul>
#foreach(var item in Model)
{
<li>#item</li>
}
</ul>
~/wwwroot/index.html
<body>
<script src="js/jquery.min.js"></script>
<script>
$.get("home/GetHelloWorld", function(data) {
$("body").html(data);
});
</script>
</body>
My problem is that I cannot get a controller working together with Razor Pages, I cannot figure out if that's even possible.
TLDR
Open Startup.cs and replace this
app.UseMvc();
with this
app.UseMvcWithDefaultRoute();
Details
The ASP.NET Core Razor Pages template (dotnet new razor) does not come with controller routes because it does not come with controllers. The easiest way to add controller routes is via UseMvcWithDefaultRoute(), which is the equivalent of the following:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
With that route installed, the URL ~/Home/GetHelloWorld maps to the HomeController.GetHelloWorld() action.
Here is a GitHub commit that demonstrates your use case in a new ASP.NET Core Razor Pages app.
See Also
https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-2.1
To do this within the RazorPage ensure that the handler method follows the convention OGet[MyMethodName] and this should resolve your routing issue
public class HomeController : Controller
{
public IActionResult OnGetHelloWorld()
{
return ViewComponent("HelloWorld");
}
}
And modify the get request to make use of the handler
<body>
<script src="js/jquery.min.js"></script>
<script>
$.get(window.location.href.split('?')[0] + "?handler=HelloWorld", function(data) {
$("body").html(data);
});
</script>
</body>
Various example are available at https://learn.microsoft.com/en-us/aspnet/core/razor-pages/?view=aspnetcore-3.1&tabs=visual-studio
I know this has been discussed a lot of times.
I basically want the possibility in my view to update a file. This file has to be mapped to the model the controller expects:
public ActionResult Create(Company company)
{
//Do something with the received model
}
The model:
public class Company
{
public int Id { get; set; }
public HttpPostedFileBase PictureUpload { get; set; }
...
}
This is working without any problems.
Now I'd like to send my form data, including the file, via AJAX.
Therefore I'm using this in my view:
#using (Ajax.BeginForm("Create", "Company", null, new AjaxOptions { HttpMethod = "Post", OnSuccess = "ajaxOnSuccess", OnFailure = "alert('Error message.');" }, new { #class = "ym-form", enctype = "multipart/form-data" }))
This is basically working but the file upload doesn't work (as far as I read ajax doesn't have access to the file so it can't be sent).
I'd like what's the best solution for this problem without having to modify my backend (controller/model).
E. g. I read this article:
http://ajeeshms.in/Blog/Article/1/upload-files-using-ajax-in-asp-mvc
It provides two nice possibilities but I'd have to modify the backend because as far as I see the automatically mapping to the HttpPostedFileBase type in my model wouldn't be possible anymore.
I don't mind using any working plugin for my view or using a technique which is supported by new browsers only.
Try this code
//Add reference to form.js
<script src="http://malsup.github.com/jquery.form.js"></script>
#using (Html.BeginForm("Create", "Company", FormMethod.Post, new { #enctype ="multipart/form-data",#id="formid" }))
{
}
//Javascript code
<script type="text/javascript">
$('#formid').ajaxForm(function (data) {
});
</script>
This will work as ajax submit.
//You can get more details on AjaxForm here
Please try this one #using (Html.BeginForm("Create", "Company", FormMethod.Post, new { id = "ym-form", enctype="multipart/form-data" }))
I have made it based on this answer from Demian Flavius:
How to do a ASP.NET MVC Ajax form post with multipart/form-data?
Basically it's the new JavaScript's FormData object that makes it easy for uploading with ajax as in the article your mentioned.
I think you cannot upload files with AJAX. One way to achieve this is to use a hidden iframe. Try this jQuery Form plugin and Telerik file control
Please refer this link also.
i am newbie knockout.js. Also i ama upper intermadiate in asp.net mvc 3. i really want to learn how to use knockout js in mvc 3 razor? but below code is not working also return to me empty total price. There is no error. Help please thanks...
Model:
public class GiftModel
{
public string Title { get; set; }
public double Price { get; set; }
}
View:
#using System.Web.Script.Serialization;
#model IEnumerable<knockout1.Models.GiftModel>
#{
ViewBag.Title = "Index";
}
<script src="/Scripts/knockout-2.1.0.js" type="text/javascript"></script>
<script type="text/javascript">
var initialData = #(new JavaScriptSerializer().Serialize(Model));
var viewModel = {
gifts : ko.observableArray(initialData)
};
ko.applyBindings(viewModel);
</script>
<h2>Index</h2>
<p>You have asked for <span data-bind="text: gifts().length"> </span> gift(s)</p>
Controller:
public class TestController : Controller
{
//
// GET: /Test/
public ActionResult Index()
{
var initialState = new[] {
new GiftModel { Title = "Tall Hat", Price = 49.95 },
new GiftModel { Title = "Long Cloak", Price = 78.25 }
};
return View(initialState);
}
}
I guess you are following this tutorial.
You have a couple of errors. First replace:
var initialData = #(new JavaScriptSerializer().Serialize(Model));
with:
var initialData = #Html.Raw(Json.Encode(Model));
This ensures that your model is properly JSON encoded. In the original article Steven Sanderson is using the WebForms view engine but you seem to be using the Razor view engine. So make sure that you adapt your syntax accordingly (don't forget that the # razor function automatically html encodes the output contrary to the <%= WebForms syntax).
And the second problem with your code is that you attempted to bind your knockout model before your DOM is ready (i.e. you have placed the ko.applyBindings(viewModel); call before the actual span containing the bindings). So either wrap your call in a $(document).ready or place your scripts at the end of the document, just before closing your </body> tag (recommended).
Also I would recommend you using url helpers to reference your scripts, don't just hardcode those urls, your application will break as soon as you publish in IIS:
#model IEnumerable<GiftModel>
<h2>Index</h2>
<p>You have asked for <span data-bind="text: gifts().length"> </span> gift(s)</p>
<script src="#Url.Content("~/Scripts/knockout-2.1.0.js")" type="text/javascript"></script>
<script type="text/javascript">
var initialData = #Html.Raw(Json.Encode(Model));
var viewModel = {
gifts : ko.observableArray(initialData)
};
ko.applyBindings(viewModel);
</script>
So as you can see the 2 problems you were having have strictly nothing to do with knockoutjs. So what I would recommend you if you want to learn some framework is to learn it independently. Don't mix up technologies or you will get mixed up.
So go ahead over the knockoutjs site and start the tutorials working on static HTML pages. Forget about ASP.NET MVC for the moment. Forget about Entity Framework. Just learn the framework starting from a static HTML page. This way you will better understand how it works.
I'm seeking to display my images with a short title in a flow from left to right as opposed to the gridview that is a sequential layout. I desire to use the pagination that the webgrid provides so as not to recreate the wheel, as it were.
I've reviewed Leek's blog post (http://msdn.microsoft.com/en-gb/magazine/hh288075.aspx) and Broer's (http://blog.bekijkhet.com/2011/03/mvc3-webgrid-html-helper-paging.html) to ensure I have a solid introduction to the use of the webgrid but I'm falling short on how to apply the pagination without using the traditional layout of the webgrid.
I am using the Razor layouts.
Ideas or thoughts?
My controller is currently:
public ActionResult Index(string cid)
{
Catalog item = new Catalog();
item.objConnection.Open();
OdbcDataReader reader = item.getCatalogItems(cid, 3);
List<Catalog> listItems = new List<Catalog>();
while (reader.Read())
{
Catalog i = new Catalog();
i.kitName = reader.GetValue(1).ToString();
i.catalogID = reader.GetValue(0).ToString();
ViewBag.CatalogName = reader.GetValue(0).ToString(); //TODO: change this to name once in place
listItems.Add(i);
}
ViewBag.ItemsPerCatagory = listItems.Count;
reader.Close();
item.objConnection.Close();
return View(listItems);
}
My View:
#model IEnumerable<MvcApplication1.Models.Catalog>
#{
ViewBag.Title = ViewBag.CatalogName;
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>#ViewBag.CatalogName (#ViewBag.ItemsPerCatagory) Items Available</h2>
<p>
Category will have a brief description here for seo purposes.
</p>
<p>
#foreach (var catalog in Model)
{
string imageUrl = "http://web3.naeir.org/images/Specials/" + #catalog.kitName + ".JPG";
<img src=#imageUrl height="150px" width="150px" /> #Html.ActionLink(#catalog.kitName, "Details", "Product", new { cid = #catalog.catalogID, itemid = #catalog.kitName }, null)
}
</p>
Upon much hacking at my code I found that a simple option exist and my solution was to use MVCPager MVC Pager Website
I was able to simply download it via VS Web Developer Express Package Manager NuGet, read the documentation and implemented the code. Pretty straight forward.
Is there something like UpdatePanel (in ASPX) for Razor?
I want to refresh data (e.g. table, chart, ...) automaticly every 30 seconds.
Similar to clicking the following link every 30 seconds:
#Ajax.ActionLink("Refresh", "RefreshItems", new AjaxOptions() {
UpdateTargetId = "ItemList",
HttpMethod = "Post"})
Edit:
I may should add that the action link renders a partial view.
Code in cshtml:
<div id="ItemList">
#Html.Partial("_ItemList", Model)
</div>
Code in Controller:
[HttpPost]
public ActionResult RefreshItems() {
try {
// Fill List/Model
...
// Return Partial
return PartialView("_ItemList", model);
}
catch (Exception ex) {
return RedirectToAction("Index");
}
}
It would be create if the PartielView could refresh itself.
You can try something similar to the following using Jquery (have not tested though)
<script type="text/javascript">
$(document).ready(function() {
setInterval(function()
{
// not sure what the controller name is
$.post('<%= Url.Action("Refresh", "RefreshItems") %>', function(data) {
// Update the ItemList html element
$('#ItemList').html(data);
});
}
, 30000);
});
</script>
The above code should be placed in the containing page i.e. not the partial view page. Bear in mind that the a partial view is not a complete html page.
My initial guess is that this script can be placed in the partial and modified as follows. Make sure that the ajax data type is set to html.
<script type="text/javascript">
setInterval(function()
{
// not sure what the controller name is
$.post('<%= Url.Action("Refresh", "RefreshItems") %>', function(data) {
// Update the ItemList html element
$('#ItemList').html(data);
});
}
, 30000);
</script>
Another alternative is to store the javascript in a separate js file and use the Jquery getScript function in ajax success callback.
Well, if you don't need the AJAX expierience than use the HTML tag:
<meta http-equiv=”refresh” content=”30; URL=http://www.programmingfacts.com”>
go here: http://www.programmingfacts.com/auto-refresh-page-after-few-seconds-using-javascript/
If someone wants the complete code for a selfupdating partial view have a look!
Code of the Controller:
[HttpPost]
public ActionResult RefreshSelfUpdatingPartial() {
// Setting the Models Content
// ...
return PartialView("_SelfUpdatingPartial", model);
}
Code of the Partial (_SelfUpdatingPartial.cshtml):
#model YourModelClass
<script type="text/javascript">
setInterval(function () {
$.post('#Url.Action("RefreshSelfUpdatingPartial")', function (data) {
$('#SelfUpdatingPartialDiv').html(data);
}
);
}, 20000);
</script>
// Div
<div id="SelfUpdatingPartialDiv">
// Link to Refresh per Click
<p>
#Ajax.ActionLink("Aktualisieren", "RefreshFlatschels", new AjaxOptions() {
UpdateTargetId = "FlatschelList",
HttpMethod = "Post", InsertionMode = InsertionMode.Replace
})
</p>
// Your Code
// ...
</div>
Code to integrate the Partial in the "Main"-View (ViewWithSelfupdatingPartial.cs):
#Html.Partial("_FlatschelOverview", Model)
The <meta refresh ..> tag in HTML will work for you. Its the best option
Traditional controls don't works in ASP MVC
You could do it using Jquery timers http://plugins.jquery.com/project/timers
Other option could be to use the Delay function
In your target is as simple as refresh the whole page, this SO link will be of your interest: Auto refresh in ASP.NET MVC
Hope It Helps.