Crystal Reports Images and ASP.Net MVC - asp.net-mvc

I am having trouble with Crystal Reports when using charts and images which use CrystalImageHandler.aspx. The image cannot display and I suspect this is due to a problem with MVC routing.
The path image path is similar to this:
src="/CrystalImageHandler.aspx?dynamicimage=cr_tmp_image_a8301f51-26de-4869-be9f-c3c9ad9cc85e.png"
With the URL similar to this:
localhost:01234/ViewCrystalReports.aspx?id=50
The image cannot be found prumably because it's looking in a non-existant directory. How can I change the path CrystalImageHandler.aspx is located at? I think if I were to reference from the root the problem would be solved but anything I change in Web.Config fails to work.
I should mention this is on a conventional aspx page, not a view etc

I solve this problem editing Web.Config file
Insert the following line:
<system.web>
...
<httpHandlers>
<add path="CrystalImageHandler.aspx" verb="GET" type="CrystalDecisions.Web.CrystalImageHandler, CrystalDecisions.Web, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"></add>
</httpHandlers>
...
*take care with write your number version (Version=xx.x.xxxx.x)

Figured it out. The routing was interfering with the CrystalImageHandler.aspx link that was being generated. Global.aspx has the following line to tell the routing engine to ignore resource files:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
but this isn't a conventional resource file, it's an aspx file for some reason (anyone know why?)
adding this fixed it:
routes.IgnoreRoute("{resource}.aspx/{*pathInfo}");

public class CrystalImageHandlerController : Controller
{
//
// GET: /Reports/CrystalImageHandler.aspx
public ActionResult Index()
{
return Content("");
}
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
var handler = new CrystalDecisions.Web.CrystalImageHandler();
var app = (HttpApplication)filterContext.RequestContext.HttpContext.GetService(typeof(HttpApplication));
if (app == null) return;
handler.ProcessRequest(app.Context);
}
}
This controller will invoke the handler. Just add a route to this as CrystalImageHandler.aspx, it can also be used with any sub path you'd like (in this case /reports). Something I could NEVER get the handler to do via configuration.

To view in local machine,you will add the following code in web config
<httpHandlers>
<add verb="GET" path="CrystalImageHandler.aspx" type="CrystalDecisions.Web.CrystalImageHandler, CrystalDecisions.Web,Version=10.2.3600.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" />
</httpHandlers>
...............................
<appSettings>
<add key="CrystalImageCleaner-AutoStart" value="true" />
<add key="CrystalImageCleaner-Sleep" value="60000" />
<add key="CrystalImageCleaner-Age" value="120000" />
</appSettings>
The following code is for displaying in server
<system.webServer>
<handlers>
<add name="CrystalImageHandler.aspx_GET" verb="GET" path="CrystalImageHandler.aspx" type="CrystalDecisions.Web.CrystalImageHandler, CrystalDecisions.Web, Version=10.2.3600.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" preCondition="integratedMode"/>
</handlers>
</system.webServer>
:) I will solve that problem in adding in web config

It's because the routing was interfering with the CrystalImageHandler.aspx. So either in Global.asax or routeConfig file we can ignore route for .aspx extension files. You can ignore .aspx extension route by adding following line.
routes.IgnoreRoute("{allaspx}", new {allaspx=#"..aspx(/.*)?"});

Related

Controller + View in a separate assembly - The name 'ViewBag' does not exist in the current context

To the mods: not a duplicate, other answers (mainly "check the web.config in the Views folder") didn't work.
I have a main asp.net MVC application which discovers controllers and views in a separate assembly: controllers with MEF and a custom ControllerFactory, views with a custom VirtualPathProvider which discovers the views embedded in the same (of the controller) assembly.
The discovery of both parts works good: the controller factory finds the controller and initializes it using Ninject, the VirtualPathProvider recognizes that it has to look for the view in the assembly and loads it.
The web.config in the Views folder of the separate assembly is the one VS2013 generated when creating a new asp.net mvc project:
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Optimization"/>
<add namespace="System.Web.Routing" />
<add namespace="Fos.WS.DemoCustomization" />
</namespaces>
</pages>
</system.web.webPages.razor>
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>
<system.webServer>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
</handlers>
</system.webServer>
</configuration>
Controller:
public ActionResult Index()
{
var dll = "~/Plugins/" + this.AssemblyName; //"~/Plugins/" is to instruct the custom viewpathprovider to discover the view from the assembly
return View(dll + "/Fos.WS.DemoCustomization.Views.Demo.Index.cshtml");
}
View:
#{
ViewBag.Title = "Demo";
}
<h2>Hi, Demo</h2>
The error i keep getting is
Compiler Error Message: CS0103: The name 'ViewBag' does not exist in the current context
Source Error:
Line 38: public override void Execute() {
Line 39:
Line 40: ViewBag.Title = "Demo";
Line 41:
Line 42: BeginContext("~/Plugins/Fos.Ws.DemoCustomization.dll/Fos.WS.DemoCustomization.Views.Demo.Index." +
Source File: c:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\482869c5\3f1d4579\App_Web_fos.ws.democustomization.views.demo.index.cshtml.41ce77d0.bg7gacz2.0.cs Line: 40
Thanks
Edit: tried to remove the viewbag part and keep just the , now the error is different:
The view at '~/Plugins/Fos.Ws.DemoCustomization.dll/Fos.WS.DemoCustomization.Views.Demo.Index.cshtml' must derive from WebViewPage, or WebViewPage.
It looks like the web.config isn't there.
Answers a little late, but I think I may be able to add a bit of insight. So i haven't worked in this exact scenario, but i have worked with MEF, and dynamic View rendering separately.
Obvious
So an obvious issue if i'm reading your setup correctly is you're relying on that web.config defined above but it is in the remote assembly. I don't believe your IOC containers are able to access the assembly definitions from the remote config.
You even recognize that it is not picking up the web config values in your question. I know you said you had tried other web config resolutions without success, but I think that will be your best bet because it needs to pull in those definitions somehow, and trying to define those manually is going to be a hack.
Less Obvious
The reason you're seeing those exceptions is the ViewData object is defined by the WebViewPage base class, your config as you can see defines that as your base class for all views. without that base class, it's not a view and not parsable.
The reason I think it was hiding this error when accessing the ViewBag explicitly is the ViewBag is a wrapper in the ViewContext, passing ViewData to a DynamicViewDataDictionary. The ViewContext won't build if you pass in null ViewData, I think by calling the ViewBag explicitly on a null ViewContext it was just blowing up earlier in the chain, or rather the compiler recognized the issue this way.
Utility Helper
Since I am sorry I can't offer a silver bullet for this issue. Just more info pointing to the web.config not pulling in. I'm going to add a fun helper, that is also a hack for getting remote/dynamic Razor Views to parse manually from a file. You can also use this to make sure remote Views are well formatted and see how they will output. If you plugged this in I bet since it's defining a RazorView which manages the WebPageView initialization in this case. It'll work for your remote Views. worth noting this is a hack and not ideal for handling all of your View Rendering but is certainly handy in some sticky corner cases.
using System.IO;
using System.Web.Mvc;
namespace Utils
{
public class RazorUtility
{
/// <summary>
/// Takes a file path to a Razor View and a controller context and renders the the View to a string
/// </summary>
/// <param name="path">file path to view</param>
/// <param name="context">controller context to render against</param>
/// <returns></returns>
public static string RenderView(string path, ControllerContext context)
{
//You need to include the Model in the ViewDate of the context passed in.
var st = new StringWriter();
var razor = new RazorView(context, path, null, false, null);
razor.Render(new ViewContext(context, razor, context.Controller.ViewData, context.Controller.TempData, st), st);
return st.ToString();
}
}
}

Miniprofiler and umbraco

I'm running an instance of umbraco 7. But I can't seem to set miniprofiler to work with it.
Set this on my global.asax:
protected void Application_BeginRequest()
{
if (Request.IsLocal)
{
MiniProfiler.Start();
}
}
protected void Application_EndRequest()
{
MiniProfiler.Stop();
}
Also defined the handler on the web.config:
<add name="MiniProfiler" path="mini-profiler-resources/*" verb="*" type="System.Web.Routing.UrlRoutingModule" resourceType="Unspecified" preCondition="integratedMode" />
Any help is truly appreciated.
MiniProfiler is built in to Umbraco v6 and v7. You don't have to manually setup it. All you have to do is to enable debug mode by setting key in AppSettings:
<add key="umbracoDebugMode" value="true" />
And load page with ?umbDebug=true query string parameter.
Does your global.asax file inherit from the umbraco global http class, or the one where you are writing this code? If the former, it won't work. Try using Web Activator instead. Or inherit from the umbraco global file in your global.asax.cs.

Can I make razor recognize .html file extension as its own?

So I can use the designer mode? I'm relying less on asp.net mvc html helpers, but not totally ditching it, opting to use plain html (in which should have no problem being rendered in Design Mode) instead
Is this possible?
Write you own View Engine
public class MyRazorViewEngine : RazorViewEngine
{
public MyRazorViewEngine()
{
base.AreaViewLocationFormats = new string[]
{
"~/Areas/{2}/Views/{1}/{0}.html",
"~/Areas/{2}/Views/Shared/{0}.html",
};
....
See System.Web.Mvc.RazorViewEngine for the rest of the locations to include
Then register it on startup
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new MyRazorViewEngine()));
RazorCodeLanguage.Languages["html"] = new CSharpRazorCodeLanguage();
and the following to your applications web.config
<system.web>
<compilation debug="true" targetFramework="4.5" >
<assemblies>
<add assembly="System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</assemblies>
<buildProviders>
<add extension=".html" type="System.Web.WebPages.Razor.RazorBuildProvider, System.Web.WebPages.Razor"/>
</buildProviders>
</compilation>
</system.web>
Upside - you get designer mode, Downside - you lose all razor highlighting and intellisense

ASP MVC Route issue with dot "."

I have this route:
file{FileId}/{name}
It works perfectly unless name has a dot in it.
For example, these work:
file1/blah, file90/foo -
but it doesn't:
file1/blah.doc
All I get in this case is 404 error. Seems like it looks for the actual file blah.doc instead of use routing system.
This problem happens only in production server. I've even tried
httpRuntime relaxedUrlToFileSystemMapping="true"
but it didn't help.
Everything after the '.' is the file extension. If that extension isn't mapped to ASP.NET, it won't get handed off to the ASP.NET handler. IIS looks for a static file instead. So you need to add a handler for your case (web.config), then your route will be able to catch the request.
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<add name="FileHandlerDot" verb="GET" path="file*/*.*" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</handlers>
</validation>

Why don't my Html Helpers have intellisense?

I can't get intellisense for my own html helpers. My CustomHtmlHelpers.cs looks like this:
using System.Web.Mvc;
using System.Text;
using System.Web;
namespace laget.Web.Helpers
{
public static class CustomHtmlHelpers
{
//MY HELPERS
}
}
and in my Web.config:
<pages>
<namespaces>
<add namespace="laget.Web.Helpers" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages"/>
<add namespace="System.Web.Helpers" />
</namespaces>
</pages>
If I put <#using laget.Web.Helpers> in my view, I get the intellisense issue fixed.
Should it not be enough with the code in Web.config?
Sometimes it doesn't seem to work right away. Try closing the .cshtml file, and re-opening it. Then if that doesn't work, try restarting Visual Studio. Also make sure you actually compiled your project, intellisense won't work with non-compiled helpers.
I'm pretty sure that you're not editing the correct Web.config file.
You need to add your namespace to the one in your Views directory.
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="laget.Web.Helpers" />
</namespaces>
</pages>
</system.web.webPages.razor>
You actually don't need to restart Visual Studio in most cases. All you need to do is close the .cshtml file and reopen it!
It needs it on the local page. I'm pretty sure this has to do with Namespace resolution. It isn't exactly sure what you are referring to without the local using statement.
I ran into this today as well. Sometimes just closing the Razor view's window in Visual Studio and re-opening it will do the trick without having to do a full Visual Studio restart.
I tried to solve an issue like this one yesterday. I had e pre-compiled dll (project name ie: MyHtmlHelpers) containing helpers and lot of other classes.
I had the assembly referenced in the web project and the all "standard"-helpers showed up in intellisense but, even though I added the namespace to both web.config in the root and in the views-folder nothing worked. When running the project helpers works, but not in intellisense.
I added a new class and wrote a new html helper inside the web project, added the namespace to web.config. And that worked.
After some hours add tried my last card, adding the MyHtmlHelpers-project to the same solution as my webproject. That did the trick. I diden't change anything in the configs just added the project to the same solution and changed the reference to point at the project insted of the compiled dll.
Isen't that strange? A VS-bug?
I found that i was adding the reference to the wrong web.config. It's not the main config but the web.config in the views directory...
So now I will show you the steps
1.Create or open an existing class library project (if you open an existing one be sure to remove the MVC5 nuget package)
2.Add the MVC (5.0) nuget package (
right click project in solution explorer -> Manage NuGet Packages -> search for MVC and install “Microsoft ASP.NET MVC”)
3.Close any and all open .cshtml files
4.Right click project -> Properties -> Build -> change Output path to your project “bin/”
5.Add the following minimal Web.config to the root of your class library project
( the web config file is solely needed for intellisense. Configuration (via Web.config)
should be done in the WebApplication hosting your ClassLibrary assembly)
6.Clean and Build the solution.
7.Open cshtml file and try now :)
I found that if it still doesn't work, you may need to go to the properties of the custom class and change the build action from "content" to "compile". That resolved it for me.
I try all of this solutions, one more thing which i didnt find is that in root web.config i must change webpages:Version from 2.0.0.0 to 3.0.0.0.
Open and close all .cshtml files and it's worked.
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />

Resources