how to configure ajax site for googlebot? - javascript

I have an angular site that I have enabled html5 mode so I can have pretty urls. I need to configure the site for googlebot. What I have done so far is put this in the meta tag:
<meta name="fragment" content="!">
My assumption is by placing that meta tag, I am informing googlebot that it is an ajax site and that it should append _escaped_fragment_ in the url right inbetween domain name and the rest of the of url. For example, if it was trying to crawl http://thehaileselassie.com/Italian_Occupation, it would transform it to http:// thehaileselassie.com/?_escaped_fragment_=Italian_Occupation. But I don't think that is what is happening. I believe it is appending it to the end, like so: http:// thehaileselassie.com/Italian_Occupation?_escaped_fragment_=. I am not quite sure what I am doing wrong.
Extra info
I have this in RouteConfig so all server calls are sent to HomeController:
routes.MapRoute(
name: "Default",
url: "{*url}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
And this is the content of the controller:
public ActionResult Index()
{
string fragment = Request.QueryString["_escaped_fragment_"];
if (fragment != null)
{
if (String.IsNullOrWhiteSpace(fragment))
{
string url = "/templates/homeView.html";
return File(Server.MapPath(url), "text/html");
}
else
{
string url = "/templates/" + fragment + ".html";
return File(Server.MapPath(url), "text/html");
}
}
return View();
}

?_escaped_fragment_= is supposed to be appended to end. What I am doing to get the part after the domain is this: Request.Url.LocalPath. This returns /Italian_Occupation. Afterwards I do some logic to create xml on the fly and return it:
string url = "/templates" + Request.Url.LocalPath + ".html";
XmlDocument doc = new XmlDocument();
try
{
doc.Load(Server.MapPath(url));
}
catch
{
return HttpNotFound();
}
var settings = new System.Xml.XmlWriterSettings();
var propInfo = settings.GetType().GetProperty("OutputMethod");
propInfo.SetValue(settings, System.Xml.XmlOutputMethod.Html, null);
var stream = new System.IO.StringWriter();
var writer = System.Xml.XmlWriter.Create(stream, settings);
// XmlElement elem = doc.CreateElement("book", "aaaa", "http://www.com");
//// doc.DocumentElement.AppendChild(elem);
// doc.DocumentElement.(elem, doc.DocumentElement.LastChild);
XmlDocument doc2 = new XmlDocument();
XmlElement element1 = doc2.CreateElement(string.Empty, "html", string.Empty);
doc2.AppendChild(element1);
XmlElement element2 = doc2.CreateElement(string.Empty, "head", string.Empty);
XmlElement element4 = doc2.CreateElement(string.Empty, "title", string.Empty);
XmlText text1 = doc2.CreateTextNode("TheHaileSelassie.Com :: "+doc.GetElementsByTagName("h1")[0].InnerText);
element4.AppendChild(text1);
element2.AppendChild(element4);
doc2.DocumentElement.AppendChild(element2);
XmlElement element3 = doc2.CreateElement(string.Empty, "body", string.Empty);
XmlDocumentFragment xfrag = doc2.CreateDocumentFragment();
xfrag.InnerXml = doc.InnerXml;
element3.AppendChild(xfrag);
doc2.DocumentElement.AppendChild(element3);
//doc2.DocumentElement.AppendChild(xfrag);
doc2.Save(writer);
return Content(System.Net.WebUtility.HtmlDecode(stream.ToString()));

Related

How do I send a django model to javascipt?

How do I pass a django model to javascript?
Specifically, I want to pass a django Movie model to javascript.
In javascript, I would like to display the id something in the movie model at the time of score with an if statement.
def index(request):
if Movie.objects.order_by('-stars').exists():
movie = list(Movie.objects.order_by('-stars'))
if TV.objects.order_by('-stars').exists():
tv = TV.objects.order_by('-stars')
print(tv)
context = {
'movie':movie,
}
return render(request, 'Movie/index.html',context)
fetchTrendingResults("all", "week")
var mediaType = document.getElementById("media_type")
mediaType.addEventListener("change", function(event) {
fetchTrendingResults(mediaType.options[mediaType.selectedIndex].value, "day")
})
function fetchTrendingResults(media_type, time_window) {
var trendingDiv = document.getElementById("trendings")
trendingDiv.innerHTML = ""
if (media_type == "score"){
var js_list = {{movie}};
}
else{
fetch(`/api/trendings?media_type=${media_type}&time_window=${time_window}`, {
method: "GET",
headers: {
"Content-Type": "application/json"
}}
// todo:movieとTVのIDをもらってこれをURLにFethして映画とTVの情報をそれぞれでスターが高い順に表示する。
)
.then(res => res.json())
.then(data => {
for (let i=0; i<data.results.length; i++) {
var mainDiv = document.createElement("div");
mainDiv.setAttribute("class", "card");
mainDiv.setAttribute("style", "width: 18rem;");
var img = document.createElement("img");
img.setAttribute("src", "https://image.tmdb.org/t/p/w200" + data.results[i].poster_path);
img.setAttribute("class", "card-img-top");
img.setAttribute("alt", "...");
var body = document.createElement("div");
body.setAttribute("class", "card-body");
var title = document.createElement("h5");
title.setAttribute("class", "card-title");
if (data.results[i].name) {
title.innerHTML = data.results[i].name;
} else {
title.innerHTML = data.results[i].title;
}
//var text = document.createElement("p");
//text.setAttribute("class", "card-text");
//text.innerHTML = data.results[i].overview;
var link = document.createElement("a");
link.setAttribute("href", "/" + data.results[i].media_type + "/" + data.results[i].id + "/");
link.setAttribute("class", "btn btn-primary");
link.innerHTML = "View Details";
body.appendChild(title);
//body.appendChild(text);
body.appendChild(link);
mainDiv.appendChild(img);
mainDiv.appendChild(body);
document.getElementById("trendings").appendChild(mainDiv);
}
})
}
}
How do I pass a django model to javascript?
Specifically, I want to pass a django Movie model to javascript.
In javascript, I would like to display the id something in the movie model at the time of score with an if statement.
You can send model data by just returning JsonResponse from the view (and for example creating JSON dict by forlooping QuerySet, or using model_to_dict Django built-in method) or by preserving your logic and sending html you need to override - even better - you can do both ways at the same time.
So, basically you write view like this:
from django.forms import model_to_dict
from django.http import Http404
def custom_ajax_view(request):
if request.method != 'POST':
raise Http404
movies = Movie.objects.order_by('-stars')
movie_dict = {}
if movies.exists():
movie_dict = {obj.id: model_to_dict(obj) for obj in movies}
tv = TV.objects.order_by('-stars')
tv_dict = {}
if tv.exists():
tv_dict = {obj.id: model_to_dict(obj) for obj in tv}
context = {
'movie': movie,
}
html = render_to_string(
'Movie/index.html', context=context)
return JsonResponse({
'movies': movie_dict,
'tvs': tv_dict,
'html': html,
})
And then you retrieve data via Ajax method (I prefer using jQuery for that) by writing:
$.ajax({
url: CUSTOM_AJAX_URL,
type: 'post',
dataType: 'json',
success: function (data) {
// Here you retrieve your data and you can do something with it.
console.log(data)
}
});
You also can resolve your CUSTOM_AJAX_URL using template logic (post it at the end of template)
<script>
const CUSTOM_AJAX_URL = "{% url 'custom_ajax_view' %}";
</script>
<script src="{% static 'your_script_name.js' %}"></script>
Then your script should see the CUSTOM_AJAX_URL (if you use script not directly by using inline method, but including script via script tag and placing it with static method in the code). If you place it directly, you can pass URL directly to the AJAX method.

Why I cannot open a CSV file using JQuery and FileContentResult

I'm trying to make an ajax call (I specifically don't want to do it using ActionLink).
I'm having a controller that is like this:
public IActionResult ExportUsers(List<string> listOfEmails)
{
/*some data processing*/
return File(result, "text/csv", "ExportCandidates.csv");
}
On the other side with ajax I do this simple call:
$.ajax({
url: '/Admin/Testcenter/GenerateInvitationPreview',
type: 'post',
data: {
//some input data to send to the controller ​
​},
​success: function (response) {
​)
​}
​});
I know there exists something for pdf files where you return a base64 file and with the response in the ajax call you just write something like pdfWindow.document.write(...) and this will open a new window with a pdf file.
Is there a way to extract the response for my CSV file and generate it so the user downloads it ?
USE NPOI Library for Excel Sheet Generation
//Generate Excel Sheet
try
{
Guid gid = Guid.NewGuid();
string ext = ".xls";
string[] Headers = { "Appointments Id", "Date of Appointment", "Doctor Name", "Patient Name", "Visit Type", "Status" };
string fileName = "AppointmentsExcelSheet_" + gid.ToString() + ext;
var serverpath = _env.ContentRootPath;
string rootpath = serverpath + "/wwwroot/ExcelSheets/" + fileName;
FileInfo file = new FileInfo(Path.Combine(rootpath, fileName));
var memorystream = new MemoryStream();
using (var fs = new FileStream(rootpath, FileMode.Create, FileAccess.Write))
{
IWorkbook workbook = new XSSFWorkbook();
ISheet excelSheet = workbook.CreateSheet("Appointments List");
IRow row = excelSheet.CreateRow(0);
var font = workbook.CreateFont();
font.FontHeightInPoints = 11;
font.FontName = "Calibri";
font.Boldweight = (short)FontBoldWeight.Bold;
for (var i = 0; i < Headers.Length; i++)
{
var cell = row.CreateCell(i);
cell.SetCellValue(Headers[i]);
cell.CellStyle = workbook.CreateCellStyle();
cell.CellStyle.SetFont(font);
}
var result = _Appointment.GetAppoinmentsPDf();
int index = 1;
foreach (var app in result.Items)
{
//var PatientDob = Convert.ToDouble(app.PatientDOB);
row = excelSheet.CreateRow(index);
row.CreateCell(0).SetCellValue(app.AppointmentId);
row.CreateCell(1).SetCellValue(app.DateofAppointment+" "+app.TimeofAppointment);
row.CreateCell(2).SetCellValue(app.DoctorFullName);
row.CreateCell(3).SetCellValue(app.SelectedPatientName);
row.CreateCell(4).SetCellValue(app.PurposeofVisit);
if (app.IsActive == false)
{
row.CreateCell(5).SetCellValue("Inactive");
}
else
{
row.CreateCell(5).SetCellValue("Active");
}
index++;
}
workbook.Write(fs);
}
using (var filestream = new FileStream(rootpath, FileMode.Open))
{
filestream.CopyToAsync(memorystream);
}
memorystream.Position = 0;
//send filepath to JQuery function
response.Msg = "/ExcelSheets/" + fileName;
}
catch (Exception Ex)
{
//exception code
}
return Ok(reponse.Msg)
//JavaScript
function AppointmentsExcelSheet() {
//var token = Token;
//var link = path;
debugger
$.ajax({
//'Content-Type': 'application/pdf.',
type: "GET",
url: "/api/Appointments/GetAppointmentsExcelSheet",
beforeSend: function () {
$.blockUI({
message: ('<img src="/images/FadingLines.gif"/>'),
css: {
backgroundColor: 'none',
border: '0',
'z-index': 'auto'
}
});
},
complete: function () {
$.unblockUI();
},
success: function (data) {
debugger
//downloads your Excel sheet
window.location.href = data.msg;
}
});
}
The best way to do what you want to do is to not use AJAX, but use either a link click that opens a new window (since you are passing in parameters) If you could use a
<form target="_blank">
to open a form response. Inside the form can be a field or fields that contains the list of emails (it can be one field, or multiple input fields with the same name). Your action handler can accept that list, parse it, and return a File response, and the natural result of opening the new window from the form post operation is a file that opens up.

Rotate individual page using itextsharp - MVC C#

i have a Generate PDF fuction, Where i am loading 3 different HTMLS as one pdf.
But i need a page which contains word "Page B" should roate to landscape..because it has some heavy GRID.
public void HTMLToPdfTEST(string[] HTML, string fileName, string folderPath, string physicalApplPath, string requestNumber = "")
{
Document document = new Document();
PdfWriter pdfwriter = PdfWriter.GetInstance(document, new FileStream(physicalApplPath + folderPath + "\\" + fileName + ".pdf", FileMode.Create));
TableHeader tevent = new TableHeader();
tevent.Header = requestNumber;
pdfwriter.PageEvent = tevent;
document.Open();
iTextSharp.text.html.simpleparser.StyleSheet styles = new iTextSharp.text.html.simpleparser.StyleSheet();
iTextSharp.text.html.simpleparser.HTMLWorker hw = new iTextSharp.text.html.simpleparser.HTMLWorker(document);
foreach (string htmlPage in HTML)
{
if (requestNumber.Contains("Page B")){
//do page rotation
hw.Parse(new StringReader(htmlPage));
}
else{
hw.Parse(new StringReader(htmlPage));
}
document.NewPage();
}
document.Close();
}
Got some solution.
//added below line and mentioned it in if condition.
document.SetPageSize(PageSize.A4);
document.Open();
foreach (string htmlPage in HTML)
{
if (requestNumber.Contains("CMC") && HTML[1] != null)
{
//do page rotation
document.SetPageSize(PageSize.A4.Rotate());
hw.Parse(new StringReader(htmlPage));
}
else
{
hw.Parse(new StringReader(htmlPage));
}
document.NewPage();
}
document.Close();
It's working now!!

Reverse Proxy Not working for Angular App

Hi I'm trying to open hosted angular app to my application without using iFrame , Object and embed tags. Below is my Handler code. Css and js files are loaded properly but site is not working as expected.
**web.config app settings:**
<add key="ProxyMode" value="1"/>
<add key="RemoteWebSite" value="http://localhost/angulartest"/>
**Handler :**
public class ReverseProxy : IHttpHandler
{
private static string GetContentType(string url)
{
if (url.ToLower().Contains(".css"))
{
return "text/css";
}
else if (url.ToLower().Contains(".js"))
{
return "application/javascript";
}
else
{
return "text/html";
}
}
/// <summary>
/// Method calls when client request the server
/// </summary>
/// <param name="context">HTTP context for client</param>
public void ProcessRequest(HttpContext context)
{
//read values from configuration file
int proxyMode = Convert.ToInt32(ConfigurationSettings.AppSettings["ProxyMode"]);
string remoteWebSite = ConfigurationSettings.AppSettings["RemoteWebSite"];
string remoteUrl;
if (proxyMode == 0)
remoteUrl = ParseURL(context.Request.Url.AbsoluteUri); //all site accepted
else
remoteUrl = context.Request.Url.AbsoluteUri.Replace("http://" + context.Request.Url.Host + context.Request.ApplicationPath, remoteWebSite); //only one site accepted
//create the web request to get the remote stream
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(remoteUrl);
//TODO : you can add your own credentials system
//request.Credentials = CredentialCache.DefaultCredentials;
HttpWebResponse response;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (System.Net.WebException ex)
{
string dsdl;
using (var sr = new StreamReader(ex.Response.GetResponseStream()))
dsdl = sr.ReadToEnd();
//remote url not found, send 404 to client
context.Response.StatusCode = 404;
context.Response.StatusDescription = "Not Found";
context.Response.Write(dsdl);
context.Response.End();
return;
}
Stream receiveStream = response.GetResponseStream();
context.Response.ContentType = GetContentType(remoteUrl);
StreamReader readStream = new StreamReader(receiveStream, Encoding.Default);
Uri test = new Uri(remoteUrl);
string content;
if (proxyMode == 0)
content = ParseHtmlResponse(readStream.ReadToEnd(), context.Request.ApplicationPath + "/http//" + test.Host);
else
content = ParseHtmlResponse(readStream.ReadToEnd(), context.Request.ApplicationPath);
//write the updated HTML to the client
context.Response.Write(content);
//close streams
readStream.Close();
response.Close();
context.Response.End();
}
/// <summary>
/// Get the remote URL to call
/// </summary>
/// <param name="url">URL get by client</param>
/// <returns>Remote URL to return to the client</returns>
public string ParseURL(string url)
{
if (url.IndexOf("http/") >= 0)
{
string externalUrl = url.Substring(url.IndexOf("http/"));
return externalUrl.Replace("http/", "http://");
}
else
return url;
}
/// <summary>
/// Parse HTML response for update links and images sources
/// </summary>
/// <param name="html">HTML response</param>
/// <param name="appPath">Path of application for replacement</param>
/// <returns>HTML updated</returns>
public string ParseHtmlResponse(string html, string appPath)
{
html = html.Replace("\"/", "\"" + appPath + "/");
html = html.Replace("'/", "'" + appPath + "/");
html = html.Replace("=/", "=" + appPath + "/");
return html;
}
///
/// Specifies whether this instance is reusable by other Http requests
///
public bool IsReusable
{
get
{
return true;
}
}
}
Controller HTML is not firing. Attached Fiddler response also.
angulartest => Hosted angular application
ReverseProxy => My own application
Inbox.html not firing in my ReverseProxy project..
Please help me for this.
Finally I found the answer. Hosted application angular js relative path not taking during Reverse Proxy. So I added in CDN version of angular js in index.html,
Now it's working perfectly.

Insert image in bootstrap popover using asp.net mvc

It is byte[] image from database, and I need to call an action.
<td><a href="#" rel="popover" class="user" data-content="
<h3>#hItem.m_sUsername</h3>
<img src=#Url.Action("Show", "Image", new {id = "1"}) alt="Image" />
<p>First name: #hItem.m_sFirstname</p>
<p>Last name: #hItem.m_sLastname</p>"
Ok, so your logic should be like this:
public class ImageController
{
[HttpGet]
public virtual ActionResult Show(int id)
{
var byteArray = YourDatabaseAdapter.LoadImage(id);
var mimeType = GetMimeType(fileName);
return base.File(byteArray, mimeType, fileName);
}
private static string GetMimeType(string fileName)
{
var mimeType = "application/unknown";
var extension = Path.GetExtension(fileName);
if (extension != null)
{
var ext = extension.ToUpperInvariant();
var regKey = Registry.ClassesRoot.OpenSubKey(ext);
if (regKey != null && regKey.GetValue("Content Type") != null)
{
mimeType = regKey.GetValue("Content Type").ToString();
}
}
return mimeType;
}
}
The generic GetMimeType function sets your content-type in http header based on file extension taken from windows registry.
EDIT (for html content):
In case of passing html code to the content, jQuery .html(); invoked on external div with the content html should work as described in the reference:
$('.user').popover({
html : true,
content: function() {
return $('#data-content-wrapper').html();
}
});

Categories