Razor engine cant find view - razor

I'm trying to render a HTML from a view without using a web request. I need the HTML as a string, internally, I do not wish to serve it.
The viewEngine.FindView() returns a viewEnineResult that shows no view was found. It shows to search locations where it looked they look like this:
/Views//PDFOperationsReportView.cshtml
/Views/Shared/PDFOperationsReportView.cshtml
(Observe the double forward slash in the first line)
File structure (I placed it into a HTML snippet cause I couldn't manage to format the text properly in this editor)
Project
Folder
Subfolder
CodeFile.cs
Views
PDFOperationsReportView.cshtml
The code:
var viewName = "PDFOperationsReportView";
var actionContext = GetActionContext();
var viewEngineResult = _viewEngine.FindView(actionContext, viewName, false);
if (!viewEngineResult.Success)
{
throw new InvalidOperationException(string.Format("Couldn't find view '{0}'", viewName));
}
var view = viewEngineResult.View;

I had the same issue. I found the answer here: GitHub aspnet/Mvc Issue #4936
Basically, use GetView instead of FindView, like this:
var viewResult = razorViewEngine.GetView(viewName, viewName, false);
Your viewName needs to be a full path for this to work. For example:
/Views/Shared/PDFOperationsReportView.cshtml
~/Pages/Shared/_Article.cshtml
~/Areas/CM/Pages/_Article.cshtml

We have a helper method defined to render optional views which may or may not exist:
public static Task RenderPartialAsyncIfExists(this IHtmlHelper htmlHelper, ICompositeViewEngine engine, string partialViewName, object model)
{
if (engine.GetView(partialViewName, partialViewName, false).Success)
{
return htmlHelper.RenderPartialAsync(partialViewName, model);
}
return Task.CompletedTask;
}
It's used on view pages like:
#inject ICompositeViewEngine Engine
...
#{ await Html.RenderPartialAsyncIfExists(Engine, $"~/Views/Shared/_navigationAdmin.cshtml"); }
This works find locally (IIS Express) but for some reason was failing when deployed to IIS.
In my case, there was something wrong with the .csproj file, where the view in question was removed but then re-added as an embedded resource:
<ItemGroup>
<Content Remove="Views\Shared\_navigationAdmin.cshtml" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Views\Shared\_navigationAdmin.cshtml" />
</ItemGroup>
Removing those two sections from the .csproj fixed the problem in IIS.
This is using (EOL) AspNet Core 2.2

Related

How do I allow an MIME extension map in ASP.NET vNext?

Background
I have a piece of LESS code that needs to be compiled at runtime with Less.js -- it calculates some things via JavaScript -- so I can't use the task runner, etc.
In my index.html, I have:
<head>
...
<link rel="stylesheet/less" href="assets/less/DynamicHeight.less" />
...
<script type="text/javascript" src="lib/less/less.js"></script>
...
</head>
Problem
Less.js appears unable to find the file:
And when I try to access the file directly, I see:
Question
How can I add the configuration that will allow this less file to be downloaded? Am I still able to use web.config files with vNext, or do I need to do something with config.json instead?
Lead 1: Should I use Owin?
Thinking this might be the right path but I'm pretty unfamiliar.
I see a number of tutorials out there, such as K. Scott Allen's, which reference code such as:
public void Configuration(IAppBuilder app)
{
var options = new StaticFileOptions
{
ContentTypeProvider = new FileExtensionContentTypeProvider()
};
((FileExtensionContentTypeProvider)options.ContentTypeProvider).Mappings.Add(
new KeyValuePair<string, string>(".less", "text/css"));
app.UseStaticFiles(options);
}
However, it appears that in its current version, asp.net is looking for a signature of Configure(IApplicationBuilder app) instead.
The IApplicationBuilder class doesn't have a method along the lines of UseStaticFiles -- it only has a signature of IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware).
I have a feeling that this is likely the right path to solve the issue -- I just can't find out how to propertly configure the IAppliationBuilder to map the MIME extension.
Okay, I believe I figured it out.
Step 1: Add the appropriate library for static files
In ASP.NET vNext, this is Microsoft.Aspnet.StaticFiles.
In your project.json file, add the following under "dependencies":
"Microsoft.AspNet.StaticFiles": "1.0.0-beta2"
This adds the static middleware method that you can use later.
Step 2: Configure the app to use Static Files
Add the using statement at the top:
using Microsoft.AspNet.StaticFiles;
At this point, the app.UseStaticFiles method will be available, so your Configure method can look as follows:
public void Configure(IApplicationBuilder app)
{
var options = new StaticFileOptions
{
ContentTypeProvider = new FileExtensionContentTypeProvider()
};
((FileExtensionContentTypeProvider)options.ContentTypeProvider).Mappings.Add(
new KeyValuePair<string, string>(".less", "text/css"));
app.UseStaticFiles(options);
}
And voila! I get text when browsing to .less files, and no more error is appearing from LessJS.
In .NET Core 1.0.1, SeanKileen answer is still good. The following is a simple code rewrite:
public void Configure(IApplicationBuilder app, ...)
var contentTypeProvider = new FileExtensionContentTypeProvider();
contentTypeProvider.Mappings[".map"] = "application/javascript";
contentTypeProvider.Mappings[".less"] = "text/css";
app.UseStaticFiles(new StaticFileOptions()
{
ContentTypeProvider = contentTypeProvider
});
The above code EXTENDS the default mapping list (see the source), which already has ~370 mappings.
Avoid using the FileExtensionContentTypeProvider constructor overload that takes a dictionary (as suggested by JHo) if you want those 370 default mappings.
SeanKilleen's answer is right on, and still works ASP.NET Core RC1. My only improvement is to write the exact same code using collection initializers to make it cleaner.
app.UseStaticFiles(new StaticFileOptions
{
ContentTypeProvider = new FileExtensionContentTypeProvider(new Dictionary<string, string>
{
{ ".less", "text/css" },
{ ".babylon", "text/json" },
// ....
})
});

how to save the data which was given inside of ckeditor into database

hello I am very new to asp.net mvc I need to save the data given in ck editor
i did like this i downloaded the ck editor from the internet and pasted in my solution explorer
given the path in view
path is like this:
<script src="~/ckeditor/ckeditor.js"></script>
written razor code for text area:
#Html.TextArea("editor", new {#class = "ckeditor", #id = "aboutme"})
how to save this data in database
Basic usage of ckeditor is as follows:
#Html.TextArea("editor", htmlAttributes: new { name = "editor", id = "editor", rows = "10", cols = "180" })
and configure your ckeditor as :
<script>
CKEDITOR.replace('editor',
{
height: 450
});
</script>
and while posting data to httpPost controller do this :
[ValidateInput(false)] <-------
[HttpPost]
public ActionResult YourController(FormCollection formValues)
{
//You can get value of ckeditor as
var temp = formValues["editor"]; //it will have complete data inside ckeditor you can save it to database as the way you want.
}
Make sure to add ValidateInput(false) because ckeditor provides output as html with html tags but in asp.net mvc due to security reasons they give exception when we post html tags so ValidateInput(false) will solve the purpose.
Make sure to add complete folder named ckeditor in your root folder of your project and also provide reference of js file in your view

Rendering an email throws a TemplateCompilationException using RazorEngine 3 in a non-MVC project

I am trying to render emails in a windows service host.
I use RazorEngine 3 forked by coxp which has support for Razor 2.
https://github.com/coxp/RazorEngine/tree/release-3.0/src
This works fine for a couple of emailtemplates but there is one causing me problems.
#model string
Click here to enter a new password for your account.
This throws a CompilationException: The name 'WriteAttribute' does not exist in the current context. So passing in a string as model and putting it in the href-attribute causes problems.
I can make it work by changing this line by:
#Raw(string.Format("Klik hier.", #Model))
but this makes the template very unreadable and harder to pass along to a marketing department for further styling.
I like to add that referencing the RazorEngine by using a Nuget package is not a solution since it is based on Razor 1 and somewhere along the process the DLL for system.web.razor gets replaced by version 2 which breaks any code using RazorEngine. It seems more interesting to use Razor 2 to benefit from the new features and to be up to date.
Any suggestions on how to fix this would be great. Sharing your experiences is also very welcome.
UPDATE 1
It seems like calling SetTemplateBaseType might help, but this method does not exist anymore, so I wonder how to be able to bind the templatebasetype?
//Missing method in the new RazorEngine build from coxp.
Razor.SetTemplateBaseType(typeof(HtmlTemplateBase<>));
I use Windsor to inject the template service rather than using the Razor object. Here is a simplified part of the code that shows how to set the base template type.
private static ITemplateService CreateTemplateService()
{
var config = new TemplateServiceConfiguration
{
BaseTemplateType = typeof (HtmlTemplateBase<>),
};
return new TemplateService(config);
}
RazorEngine 3.1.0
Little bit modified example based on coxp answer without the injection:
private static bool _razorInitialized;
private static void InitializeRazor()
{
if (_razorInitialized) return;
_razorInitialized = true;
Razor.SetTemplateService(CreateTemplateService());
}
private static ITemplateService CreateTemplateService()
{
var config = new TemplateServiceConfiguration
{
BaseTemplateType = typeof (HtmlTemplateBase<>),
};
return new TemplateService(config);
}
public static string ParseTemplate(string name, object model)
{
InitializeRazor();
var appFileName = "~/EmailTemplates/" + name + ".cshtml";
var template = File.ReadAllText(HttpContext.Current.Server.MapPath(appFileName));
return RazorEngine.Razor.Parse(template, model);
}

Html Image src path with shared network is not working in firefox

In My webpage i am using a image tag, the src attribute is pointing to shared network location ie (/server/images/image1.png). The exact script is "<img src="file://///server/images/image1.png". It is working fine in IE. In firefox, when I do debug using firebug its showing image, but it's not displayed in page (user view). Even it's working fine when copy this location and place it in firefox address bar. What will be the problem while using img tag also what is the solution for this? Thanks in advance.
Putting this as an answer here so as to provide help for others like myself that was searching for how to display networked images and came accross this SO post in the top 3 search engine results. It also seems like a better answer than the java servlet issuing images in the response.
FireFox would not display networked images so I created an MVC helper that extends HtmlHelper.
public static class ImageHelper
{
/// <summary>Converts a photo to a base64 string.</summary>
/// <param name="html">The extended HtmlHelper.</param>
/// <param name="fileNameandPath">File path and name.</param>
/// <returns>Returns a base64 string.</returns>
public static MvcHtmlString PhotoBase64ImgSrc(this HtmlHelper html, string fileNameandPath)
{
var byteArray = File.ReadAllBytes(fileNameandPath);
var base64 = Convert.ToBase64String(byteArray);
return MvcHtmlString.Create(String.Format("data:image/gif;base64,{0}", base64));
}
}
use in the MVC View like so:
using
<img src="#Html.PhotoBase64ImgSrc(image)" height="60px" width="60px" alt="photo" />
here the 'image' in #Html.PhotoBase64ImgSrc(image) is a pure network UNC, e.g.
//Photos/ebaebbed-92df-4867-afe8-0474ef8644eb.jpg
Create a regular HTML img element like so:
<img id="image1" runat="server" ImageUrl=<%# Eval("Value") %>/>
And in code behind do this:
image1.ImageUrl = "data:image/png;base64," + Convert.ToBase64String(bytes);
Where bytes is a byte[].
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["FileName"] != null)
{
// Read the file and convert it to Byte Array
string filePath = "C:\\Users\\Public\\Pictures\\Sample Pictures\\";
string filename = Request.QueryString["FileName"];
string contenttype = "image/" + Path.GetExtension(filename).Replace(".", "");
FileStream fs = new FileStream(filePath + filename, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
Byte[] bytes = br.ReadBytes((Int32)fs.Length);
br.Close();
fs.Close();
image1.ImageUrl = "data:image/png;base64," + Convert.ToBase64String(bytes);
}
}
You are done. The image will be displayed.
The solution usually is: use a web server.
You may have to make it like so.
<img src="../server/images/image1.png" />
Once you add the "../" it is basically telling your browser to go back one directory to search for the location after the "../" .
Where is the file located and where is the location of your HTML document?
UPDATE:
I do all of my work on a Network Server as well... This should do the trick.
<img alt="" src="file:///SERVER:/FOLDER/IMAGES/image1.png" />
Thanks,
Aaron
I wrote a servlet which reads the file from LAN using Java File Stream and sets it in response and it does the trick. Thanks to all for valuable response.

HTML to PDF Solution (Handling Content, Headers and Footers)

I'm trying to create a "report" by generating a PDF based on HTML.
At first, I simply attempted to write raw encoded HTML to a document and then print that document using Javascript. However, this gave me little to no control involving headers and footers.
I attempted using thead and tfoot elements, which worked reasonably well in most browsers, however I wasn't able to get the formatting that I was looking for.
Currently - I am trying to work on a server-side solution using iTextSharp in MVC3, however I am a bit lost as to how to proceed, having not worked with iTextSharp much.
Input and Description of Output:
There will be 4 items used in creating the Report:
Report Content (which is currently encoded HTML, as I am unsure if decoding will change any formatting)
Report Title (will simply be the name of the PDF generated)
Report Header (will be displayed at the upper-left of each page)
Report Footer (will be displayed at the lower-left of each page)
Controller Action:
//This will be accessed by a jQuery Post
[HttpPost]
public FileStreamResult GeneratePDF(string id)
{
//Grab Report Item
ReportClass report = reportingAgent.GetReportById(id);
Document doc = new Document();
//Do I need to decode the HTML or is it possible to use the encoded HTML?
//Adding Headers / Footers
//Best method of returning the PDF?
}
iTextSharp cannot convert HTML to PDF. It's not what it was designed to do. It was designed to create PDF files from scratch, not converting between various formats into PDF. If you want to convert HTML into PDF you could for example use the the flying-saucer library which is based on iText. I have blogged about how this could be done in .NET using IKVM.NET Bytecode Compiler (ikvmc.exe).
So your controller action might look something along the lines of:
[HttpPost]
public FileStreamResult GeneratePDF(string id)
{
ReportClass report = reportingAgent.GetReportById(id);
return PdfResult(report.Html);
}
where PdfResult could be a custom action result taking the raw HTML and outputting the PDF into the response stream:
public class PdfResult : ActionResult
{
private readonly string _html;
public PdfResult(string html)
{
_html = html;
}
public override void ExecuteResult(ControllerContext context)
{
var response = context.HttpContext.Response;
response.ContentType = "application/pdf";
var builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
using (var bais = new ByteArrayInputStream(Encoding.UTF8.GetBytes(_html)))
using (var bao = new ByteArrayOutputStream())
{
var doc = builder.parse(bais);
var renderer = new ITextRenderer();
renderer.setDocument(doc, null);
renderer.layout();
renderer.createPDF(bao);
var buffer = bao.toByteArray();
response.OutputStream.Write(buffer, 0, buffer.Length);
}
}
}