Using AJAX in Sitecore rendering with XSLT - asp.net

I am new to Sitecore and .NET. I got an old existing project which is based on Sitecore 6.5 and rendered content by XSLT with .NET Framework 3.5.
Now what I need to create a page that can make an AJAX call so that the page need not to be refreshed and new content can be generated. I am quite familiar with AJAX call with PHP, yet I am quite confused on those in .NET.
I googled and found most of the tutorial are based on Razor view rendering.
Can anyone provide me a full picture that how can I do to meet my objective?
I wonder if the following steps are correct:
Create a .xslt for rendering different content based on matching the URL parameter that passed into
Create a .ashx to get the .xslt content
JavaScript AJAX call to the .ashx and convert the xml content to HTML
Any examples that I can follow?
Thanks!
============================================
Update:
I tried the above flow and can print Hello World by AJAX successfully.
However, I am not sure how to get the content from XSLT in the following .ashx file with different parameter?
And are there any HttpPost/IsPostBack that can help to check if the .ashx is visited by a POST method?

I finally solved the question with the following steps.
Create a .ashx to render the sitecore content.
I have compared with .ashx, .aspx and .asmx. Seems .ashx is the best choice.
using Sitecore.Configuration;
using Sitecore.Data;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MYPROJECT.Web
{
/// <summary>
/// Summary description for AjaxTest
/// </summary>
public class AjaxTest : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/html";
string ID = context.Request.QueryString["ID"];
Database master = Factory.GetDatabase("master");
Item source = master.GetItem("/sitecore/content/Home/MYPROJECT/gallery");
Item[] items = source.GetChildren().ToArray();
context.Response.Write(items[ID].Fields["image"].Value);
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
p.s I removed some validation codes from above.
JavaScript AJAX call to the .ashx.
$j('#ajax_test').click(function(){
$j.ajax({
//type: 'POST',
url: '/AjaxTest.ashx?ID='+$j('#inputunmber').val(),
//dataType: 'html',
//data: form.find(':input').serialize(),
success: function( response ) {
$j('.test_result').append(response);
},
error: function (xhr) {
alert("Error:" + xhr.responseText);
}
});
});

Related

Custom Routing in ASP.NET Core 2.2 Razor Pages

I'm having trouble setting up a routing convention for Razor Pages in an ASP.NET Core 2.2 application (I'm migrating from traditional MVC to Razor Pages).
I am using the standard Pages folder structure as recommended in the documentation, but I want to customise the generated routes slightly.
For example, on a Details.cshtml page in the Products folder I have the following directive:
#page "{id:int}
The URL for this page is:
/Products/Details/42
however I want the URL to be:
/Products/42
I want this to be globally applicable, not just on the Product Details page. The documentation is not particularly clear on this.
So this seems to be the way to do it:
https://www.mikesdotnetting.com/article/327/customising-routing-conventions-in-razor-pages
Create a class that implements IPageRouteModelConvention:
public class CustomPageRouteModelConvention : IPageRouteModelConvention
{
public void Apply(PageRouteModel model)
{
foreach (var selector in model.Selectors.ToList())
{
var template = selector.AttributeRouteModel.Template;
if (template.EndsWith("Details/{id:int}", StringComparison.OrdinalIgnoreCase))
selector.AttributeRouteModel.Template = template.Replace("Details/{id:int}", "{id:int}", StringComparison.OrdinalIgnoreCase);
}
}
}
Register the class in Startup.cs:
services
.AddMvc()
.AddRazorPagesOptions(o =>
{
o.Conventions.Add(new CustomPageRouteModelConvention());
});
Compared to the old MVC way of doing it this seems like a massive effort, but I can see that it allows for a finer level of control.
You need to override the entire route, so this is what you needed -
#page "/Products/{id:int}"

MVC4 Ajax forms: How to display server side validation

I am using #Ajax.BeginForm helper method, which submits form data to the server by Ajax. When the data arrive to the server, some server side validation is processed and final result is passed back to the browser.
My problem is, I want the errors to be displayed without page refresh. I have found plenty of questions based on this but they are old. I am wondering if there is some new way how to achieve this. The best way I have found so far is to process the result using jQuery. But maybe in new MVC4 there is some built in functionality how to achieve this problem in a better way?
Your view should look similar to this:
<div id="update-this">
#using (Ajax.BeginForm("YourAction", new AjaxOptions { UpdateTargetId = 'update-this' }))
{
}
</div>
Also use #Html.ValidationMessageFor(model => model.someField) next to your fields to display the error message.
On server side return a partial view if there was any error:
public ActionResult YourAction(YourModel yourmodel)
{
if (ModelState.IsValid)
{
// Do what is needed if the data is valid and return something
}
return PartialView("DisplayPartial", yourmodel);
}
And use Data Annotations on your model to make it work. (Tutorial here.)

ASP.NET MVC 2.0 How to pass data from controller to Jquery

Iam trying to pass data from my controller, and put it into the variable in JS script. I have done it before and it worked perfectly, thats why this one puzzles me even more.
Here is my code of the controller:
public ActionResult GetCategories()
{
var categories = categoryRepository.ListActiveCategories().ToList();
return View(categories);
}
And this is my JS code in the view:
<script type="text/javascript" src="http://ajax.microsoft.com/ajax/jQuery/jquery-1.4.1-vsdoc.js"></script>
<script type="text/javascript">
var categories = JSON.parse('<%= Model %>');
</script>
And this is the output I get on my website in the browser:
<script type="text/javascript" src="http://ajax.microsoft.com/ajax/jQuery/jquery-1.4.1-vsdoc.js"></script>
<script type="text/javascript">
var categories = JSON.parse('System.Collections.Generic.List`1[SklepOnline.Category]');
</script>
In chrome I also get an error "Uncaught SyntaxError: Unexpected token ILLEGAL".
Any ideas what is wrong in this code? I am pretty sure it is the same I use for my other project and that one works just great so I really dont know what is wrong. Any help would be much appreciated.
Best Regards
Bhaal275
You need to render a javascript string that can be parsed by JSON.parse().
Use JavaScriptSerializer to do that (this is an extention method for HtmlHelper):
public static IHtmlString ToJson(this HtmlHelper instance, object data)
{
var serializer = new JavaScriptSerializer();
return new HtmlString(serializer.Serialize(data));
}
Then in View:
var categories = JSON.parse('<%= Html.ToJson(Model) %>');
Don't use another controller action (as suggested by Scott Anderson) cause it requires another round-trip to the server.
You need to return JsonResult via Json method in controller.
From what I gather, you are trying to return a JSON object from your action. If this is the case, you don't actually need a view for it at all. As long as your SklepOnline.Category object is serializable, you can return a Json representation of that object with an action like this:
public JsonResult GetCategories()
{
var categories = categoryRepository.ListActiveCategories().ToList();
return Json(categories);
}
Now, to consume this object, you can grab it with a simple AJAX call from your JavaScript within any view. This example uses jQuery:
$.getJSON('MyController/GetCategories', function(categories) {
// now I have a JSON object called "categories" with my data
});
This saves you from having to write a view at all, and the data will be loaded via AJAX in the background. Good luck.

ASP.NET MVC2: modifying master css property depending on query string parameter

I am migrating a web site to a new one using ASP .NET MVC2.
In the original site, master page has code-behind to check a query string parameter value. Depending on this value, code-behind dynamically modify some CSS property to hide / display master page elements.
As MVC2 has no code-behind because we are supposed to perform everything in the controllers, how should I proceed in this case ?
I see this : asp.net mvc modifying master file from a view
It partially answers my needs but the query string processing is common to all pages. How can I move this processing in a common code section ?
Regards.
A helper method looks like a good place:
public static class HtmlHelperExtensions
{
public static string GetCss(this HtmlHelper htmlHelper)
{
// read some request parameter
// here you also have access to route data so the
// parameter could be part of your custom routes as well
var foo = htmlHelper.ViewContext.HttpContext.Request["foo"];
// based on the value of this parameter
// return the appropriate CSS class
return (foo == "bar") ? "barClass" : "fooClass";
}
}
And somewhere in your master page:
<body class="<%= Html.GetCss() %>">
Or if you are always going to apply it to the body tag only it might be more appropriate to do this in order to reduce the tag soup:
public static class HtmlHelperExtensions
{
public static MvcHtmlString StartBody(this HtmlHelper htmlHelper)
{
var body = new TagBuilder("body");
var foo = htmlHelper.ViewContext.HttpContext.Request["foo"];
var bodyClass = (foo == "bar") ? "barClass" : "fooClass";
body.AddCssClass(bodyClass);
return MvcHtmlString.Create(body.ToString(TagRenderMode.StartTag));
}
}
and in your master page at the place of the body tag:
<%= Html.StartBody() %>
I can think of two solutions to this:
Derive your controllers from one controller base and set the ViewData parameter there depending on posted Form values
Don't use ViewData at all, but simply look for the form value in the view (using HttpContext.Current)
The second method violates the MVC pattern. IMO it is still acceptable in some scenarios, for example I am using this approach to highlight the currently selected item in a navigation menu.

Can you do ajax without using ASP.net ajax toolkit?

Can you do ajax on ASP.net webform without using ajax toolkit? (Please post a example link)
yes... see my example in this post
AJAX - How to Pass value back to server
This can perform much better than ASP.NET ajax, but does take longer to code.
Sure. People have been doing ajax for years before the term ajax was even coined. Jquery is a popular library that you can use to make calls back to the server without a page refresh.
Certainly you can! What I did in .NET 1.1 (before ASP.Net Ajax was released) was to define an HttpHandler to listen on calls to ajax.aspx, run the appropriate methods, and spit back out the result. I used the Prototype library to make the Ajax call, though you could use any other, or do it by hand.
I'm going by memory, but here's the code I used (for .NET 2.0, but you get the idea):
// client-side js:
var foo = new Ajax.Request('ajax.aspx',
{
method:'get',
parameters: { method: 'GetFive' },
onSuccess: function(transport){
var response = transport.responseText || "no response text";
alert("Success! \n\n" + response);
},
onFailure: function(){ alert('Something went wrong...') }
});
// web.config:
<httpHandlers>
<!-- pre existing handlers go here -->
<add verb="GET" path="ajax.aspx" type="Fully.Qualified.Name.AjaxHandler, AssemblyName" validate="false" />
</httpHandlers>
// AjaxHandler.cs
public class AjaxHandler : IHttpHandler {
internal delegate object AjaxFunction();
private Dictionary<string, AjaxFunction> functions;
public bool IsReusable {
get { return true; }
}
public void ProcessRequest(HttpContext context) {
this.functions = new Dicionary<string, AjaxFunction>();
this.functions.Add("GetFive", delegate() {
return 5;
});
string functionName = context.Request["method"];
AjaxFunction func = this.functions[functionName];
if (func != null) {
object val = func();
context.Response.Write(val);
}
}
}
[Big note: the above is untested and not really designed well, and may not even compile, but it should give you the right idea.]
Here's a popular tool: AjaxPro.
As others have noted, you can code the entire thing yourself using XmlHttpRequest objects and javascript. But if your app will be using very sophisticated techniques, writing the code yourself becomes quite tedious. The tools have become much more powerful and easy to use.
Parenthetically, there are two elements to ASP.Net Ajax. One is the Ajax Extensions that are included in Visual Studio 2008 and can be added to Visual Studio 2005. This can be used for much more functionality than the "toolkit". Things like partial page refreshing and retrieving data without performing a full postback. The other is the Ajax Control Toolkit, which is a separate download. The "toolkit" primarily includes fancy controls, especially ones with DHTML effects (show, hide, mimic animation).
Oh absolutely.
There are libraries such as jQuery that you can use in your ASP.NET forms instead of UpdatePanel and all the paraphernalia that surrounds it.
Where I used to work we were doing AJAX long before there was a word for it. This was in the days when our stuff only used to work in IE :-)
One thing you need to do in ASP.NET forms where you're using ASP.NET server controls is use the correct client ID that the server generates for your controls when referencing them from javascript. So if you have a label with an ID of say 'telephoneNumber', you need to reference it as <%=telephone.ClientID %>. e.g.
$("#<%=telephoneNumber.ClientID %>").attr("disabled", "disabled");
With libraries such as jQuery you can still call your ASP.NET webservices but you're probably better of investigating WCF and JSON serialisation.
You don't have to throw away everything in the ASP.NET ajax bits, I still make calls to web services using script services. It's a half way house until I can replace with JSON:
http://msdn.microsoft.com/en-us/magazine/cc163499.aspx
Ajax just means while user is looking at your web page, with javascript, go back to the server and fetch something else. Then update the page with what you fetched, using javascript, the DOM.
The XMLHttpRequest object is nice, but even before it, you could do the same thing using a hidden IFRAME....
Here is all the javascript code you need to get started:
function GetXmlHttpObject()
{
var objXMLHttp=null
if (window.XMLHttpRequest)
{
objXMLHttp=new XMLHttpRequest()
}
else if (window.ActiveXObject)
{
objXMLHttp=new ActiveXObject("Microsoft.XMLHTTP")
}
return objXMLHttp
}
function stateChanged()
{
if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")
{
// do something with xmlHttp.responseText
}
}
function SendAsyncHttpRequest()
{
xmlHttp=GetXmlHttpObject()
if (xmlHttp==null)
{
return
}
var url = "http://YOUR_URL"
xmlHttp.onreadystatechange=stateChanged
xmlHttp.open("GET",url,true)
xmlHttp.send(null)
}
YES!
There are a "gazillion" alternatives to ASP.NET AJAX out there. Most of them are better in fact too. You might want to check out my project; Ra-Ajax for your needs :)

Resources