Using a Razor #functions in several webpages (.cshtml files) - asp.net

I have the below function that I would like to be available to several .cshtml views in my asp.net web pages 2 application. How can I make this function available to any view in the application (as opposed to just one).
#functions {
public bool DisplayButton(String startDate, String endDate)
{
return Convert.ToDateTime(startDate) < DateTime.Now && Convert.ToDateTime(endDate) > DateTime.Now;
}
}

Create a file called Functions.cshtml in App_Code and then paste the code you have into the file. Then you can call the DisplayButton method in any .cshtml file by prefixing it with the file name:
var myBool = Functions.DisplayButton(DateTime.Now, DateTime.Now.AddDays(30));
For more on working with functions and helpers in ASP.NET Web Pages, read this: http://www.mikesdotnetting.com/Article/173/The-Difference-Between-#Helpers-and-#Functions-In-WebMatrix

You can define "global" helper functions in a Razor file in the AppCode directory as described here: http://weblogs.asp.net/scottgu/archive/2011/05/12/asp-net-mvc-3-and-the-helper-syntax-within-razor.aspx. However, helpers only render page elements; they cannot return a value (or more correctly, the returned value is the HTML markup to be rendered).
If you need to return a value, your best bet is an extension method.

Don't see why you couldn't have a static class with a static method and just include it at the top of every view and then use it

Related

How to generate js file based on script content returned by api in .net core

i have two api return script context i need to generate the .js file based on the script content returned by the two interfaces under the wwwroot / js / directory
"~/AbpServiceProxies/GetAll" and "~/AbpScripts/GetScripts"
In your controller must have some code like this:
public ActionResult SomeAction(Model model)
{
if(model!=null )
ViewBag.JSFileName = "Some.js";
else
ViewBag.JSFileName = "AnotherJs.js";
return View();
}
and after that in SomeAction.cshtml
<script src="~/AbpScripts/GetScript/#(ViewBag.JSFileName)"></script>
This question can be implemented in many ways.

The resource name is not a valid identifier for devexpress gridview

I want to translate DevExpress GridView filter text from English to Persian.
I added a .resx file into asp.net project and fill it.
But I have some problem.
The resource name ASPxGridViewStringId.GroupPanel is not a valid identifier.
After added this .resx file, and run project, not happen any thing.
How can I fix this problem?
OK!!!! I do it, according to the similar question in this page, I added two ".resx" into App_GlobalResources folder.
one of them is default lang "English" and other is target lang "Persian".
DevExpress_Web_ASPxGridView_v15_1.rexs = default
DevExpress_Web_ASPxGridView_v15_1.Fa.resx = target
and translate it's values to persian.
finally change "UICULTURE" to "fa-ir".
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" UICulture="fa-ir" %>
Thanks God :) .
i put this answer in Devexpress
You can take a look at DevExpress Documentation topic called «Localization»:
DevExpress ASP.NET controls can be localized using one of the
following methods.
Via Satellite Resource Assemblies.This is the most universal approach, commonly used for all DevExpress products and under all
supported technologies.
Localizing ASP.NET Controls via Localizer Objects.This approach is appropriate if you are developing an application for a single culture
and you wish to translate resources into a specific language, or you
wish to change the default resources (for the English-US culture) to
their equivalents.
Satellite Resource Assemblies
You can create your translation via Localization Service:
After completing the translation you can save it, download it as the assembly and add it into your project:
To add localized resources to your application, copy satellite
assemblies from the unpacked archive to the corresponding subfolders
of your application's directory. The subfolder's name is the culture's
abbreviation. For example, to include German assemblies, copy the
folder named de from the \Bin\Framework\ directory to the Bin
directory of your application.
Localizer Objects
You can create custom localizer object for your translation and use it in your application. For GridView your object must be derived from ASPxGridViewLocalizer class or from ASPxGridViewResLocalizer class. In your descendant class you must ovveride XtraLocalizer(T).GetLocalizedString method. This method is using ASPxGridViewStringId enumeration as parameter.
Here is example:
public class CustomGridViewLocalizer : ASPxGridViewResLocalizer
{
public static void Activate()
{
var localizer = new CustomGridViewLocalizer();
var provider = new DefaultActiveLocalizerProvider<ASPxGridViewStringId>(localizer);
SetActiveLocalizerProvider(provider);
}
public override string GetLocalizedString(ASPxGridViewStringId id)
{
switch (id)
{
case ASPxGridViewStringId.AutoFilterBeginsWith:
return "شروع با";
case ASPxGridViewStringId.AutoFilterContains:
return "شامل";
case ASPxGridViewStringId.AutoFilterDoesNotContain:
return "شامل نمی شود";
case ASPxGridViewStringId.AutoFilterEndsWith:
return "به پایان می رسد با";
case ASPxGridViewStringId.AutoFilterEquals:
return "برابر";
case ASPxGridViewStringId.AutoFilterNotEqual:
return "نا برابر";
default:
return base.GetLocalizedString(id);
}
}
}
You need to activate this object in the Application_Start event handler within the Global.asax file:
protected void Application_Start(object sender, EventArgs e)
{
CustomGridViewLocalizer.Activate();
}

Calling methods in App_Code from an ASP.NET Custom Control

I am using VS2008 and have a solution file which contains 1 Website and 1 Class Library Project.
The Class Library is a Custom Control which derives from Label. The Website contains a reference to the control - it builds successfully and the compiled .dll gets added to the Website's /bin folder. I can then use it in any of the website's .aspx pages without error.
What I cannot do, however, is reference any of the Website's data access methods that are in static classes in /App_Code from within the custom control.
I don't want to repeat the website data access logic all over again within the custom control when I know it will already exist in the website - I just want to be able to call a method from a class in /App_Code . If I try and reference anything in /App_Code from within the Class Library, it fails to build and says it can't find the Namespace or that it doesn't exist in the current context.
How can I achieve this so that the Custom Control builds as a standalone control, but can make use of classes in the website it gets used in? Delegates, possibly? Was hoping it might be more straightforward than that.
EDIT: I should add that the reason the control is in a separate Class Library is so that I can include JavaScript as an embedded resource within the Control. So when it's used in a .aspx page, it adds a WebResource.axd? style link to the page instead of a load of plaintext JavaScript in the <head> section.
EDIT 2:
In the website App_Code folder, I have a static class that handles data access (snippet):
[DataObject]
public static class DBAccess
{
[DataObjectMethod(DataObjectMethodType.Select)]
public static DataTable GetSomeData(Int32 SomeParam, DateTime OtherParam)
{
SqlConnection cn = SqlLibrary.GetConnection(DBConnectionString);
DataTable _dt;
SqlLibrary.SProcFill(out _dt, cn, "usp_SomeData_Select", SomeParam, OtherParam);
return _dt;
}
}
In the Class Library's custom control (which I want to build independently of the website's existence, yet be capable of calling its methods when used as a control in an .aspx page):
namespace MyCustomControls
{
public class StatusControl : Label
{
private Int32 _someProperty = -1;
private DateTime _otherProperty = DateTime.Now;
public StatusControl()
{
//some constructor logic
}
public void FetchData()
{
//what I'd **like** to do here is:
DBAccess.GetSomeData(_someProperty, _otherProperty);
//...but DBAccess isn't "visible" to this control at build time
}
}
}

Create Instance Aspx Page of Ascx Control In a Back End Class without Loading FilePath

Question: Is it possible in back end code (not in the code behind but in an actual back end class) to load and render a page or control defined in a .aspx or .ascx without having to use Load(path) and instead just create an instance of the page/control class?
I want to be able to do this (from a back end class NOT a code behind):
MyControl myCtl = new MyApp.Views.Shared.MyControl();
String html = Util.ControlToString(myCtl); //I get an empty string & hidden errors
instead of this
public static string ControlToString(string path)
{
Page pageHolder = new Page();
MyControl myCtl = (MyControl)pageHolder.LoadControl(path);
pageHolder.Controls.Add(myCtl);
StringWriter output = new StringWriter();
HttpContext.Current.Server.Execute(pageHolder, output, false);
return output.ToString();
}
Details:
In a Asp.net WebApp I occasionally need to render a user control (.ascx) or page (.aspx) as a HTML string. When a page or control inherits from a code behind, its class shows up in intellisense in my back end code and I can create an instance and set properties without getting compile time or run time errors. However, when I try to render the page or control I always get an empty string and upon inspection the page or control shows suppressed internal rendering errors unless I load the page or control using its physical file path.
I think the key issue has to do with when & how the .aspx / .ascx files are runtime compiled. I don't want to create a pre compiled class library of user controls because that would make the design process awkward and I really like the designer features offered by the .aspx / .ascx pages and so I'd love to find a way to make the pages compile in the solution so that they are usable like any other back end class but can still be created using the designer. I want the best of both worlds (1) to be able to edit pages and controls in the designer and (2) create instances and set their properties using back end classes.
Here is an approach that may help in situations like this.
The "back-end" code may not know where the user control is located, but the User Control does know where it is.
So, in the User Control, add a static method like this:
public partial class MyControl : UserControl
{
...
public static MyControl LoadControl(CustomDto initialData)
{
var myControl =
(MyControl)
((Page) HttpContext.Current.Handler)
.LoadControl("~\\UserControlsSecretPath\\MyControl.ascx");
myControl._initialData = initialData;
return myControl;
}
...
private CustomDto _initialData;
}
(The CustomDto is included to illustrate how initial data can be passed to the User Control. If you don't need to do that, take it out!)
With this, the code that loads the user control does not need to know the path to where the user control is physically located. If that location ever changes, then update this one location. All other code that uses this UserControl is unchanged.
In your back-end code, or anywhere else, you can do something this:
var control = MyControl.LoadControl(customDto);
PlaceHolder1.Controls.Add(control);
Generally speaking: no.
As far as I know, ASP.NET inherits from your classes to combine the .aspx/.ascx template with your code. This is why your controls show up empty: the code to combine the template with your code is missing. This is usually done by ASP.NET the first time you access a page or user control (that's precisely why the first hit is a little slow: it's actually generating and compiling the hookup-code).
For precompiled websites ASP.NET generates this code as part of your precompiled website's .dll in advance, which is why such sites load quicker. However, IIRC you'll still need to instantiate the generated classes rather than your original classes.
It's a pretty common request, but so far MS has not provided the tools to do this.
Edit: Although I fail to see why you'd want to render a control to an in-memory string, I might have a solution to the build problems.
If you stick to non-compiled .ascx files (using the web site model rather than the web application model), you can actually develop them separately by placing them physically in subfolder of your main project, and treat them as content files only. Then, you can make a separate project with this subfolder as the root folder. You only need to treat the files in this subfolder as web site files, the main project can still be a web application. (Actually recommended, 'cause you don't want the .csproj files included in the main project.)
However, shared code (that is, shared between the controls project and the main project) should be put in a separate library project, so you can compile each project separately without interdependencies.
Using LoadControl within the main project will compile them on the fly (code behind is possible); if you need to set properties, you must however define interfaces in the shared project, implement them on the appropriate user controls and cast the control created by LoadControl to the appropriate interface.
I developed a solution that solves my problem in VS 2008:
Create Main Site Solution: Create a MVC 1 Website solution in
VS 2008
Create Model Class Library: Add a Class Library for the Model Code
Create View Code: Add an "Empty Website" to hold the .ascx pages, and add a reference the model library
Create Deployment Site: Add a deployment project that compiles the "Empty Website" goto the "properties page" and Check: "Merge All outputs into a single assembly" and "Treat as library component" and be sure to UnCheck: "Allow this precompiled site to be updatable"
Reference Deployment Output: In the main project add a reference to the output of the Deployment site.
ASP. - Compiled Controls: Controls show up under the ASP. namespace and are named in two ways
A. if the .ascx / aspx page did not declare a "ClassName" then they are named using their folder and file name with underscores ex. <%# Control Language="C#" ClassName="Admin_Index" %>
B. if they did declare a class name then that is their name
List item
Usage: Example code is below
Here is an example usage
public ActionResult Index()
{
var ctl = new ASP.Directory_FirmProfile(); //create an instance
ctl.Setup(new MyDataModel); //assign data
//string test = CompiledControl.Render(ctl); //output to string
return new HtmlCtl.StrongView(ctl); //output to response
}
public class CompiledControl
{
public static string Render(Control c)
{
Page pageHolder = new Page();
pageHolder.Controls.Add(c);
StringWriter output = new StringWriter();
HttpContext.Current.Server.Execute(pageHolder, output, false);
return output.ToString();
}
public static void Render(Control c, StringWriter output)
{
Page pageHolder = new Page();
pageHolder.Controls.Add(c);
HttpContext.Current.Server.Execute(pageHolder, output, false);
}
public static void Render(Control c, HttpResponseBase r)
{
Page pageHolder = new Page();
pageHolder.Controls.Add(c);
HttpContext.Current.Server.Execute(pageHolder, r.Output, false);
}
}
public class StrongView : ActionResult
{
private Control ctl;
public StrongView(Control ctl)
{
this.ctl = ctl;
}
public string VirtualPath{get;set;}
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
HtmlCtl.CompiledControl.Render(ctl, context.HttpContext.Response);
}
}
I've come up with a simpler solution along the lines of Ruben's advice.
It has worked without problems for about a month:
//Example usage
//reference the control
var emailCTL = new HtmlCtl.ControlOnDisk<MyControlType>(#"~\Views\EmailTemplates\MyControlType.ascx");
//if you have a code behind you will get intellisense allowing you to set these properties
// and re-factoring support works most places except the template file.
emailCTL.c.title = "Hello World "; //title is a property in the code behind
emailCTL.c.data = data; //data is a property in the code behind
string emailBody = emailCTL.RenderStateless();
//Helper Class
public class ControlOnDisk<ControlType> where ControlType : UserControl
{
public ControlType c;
Page pageHolder = new Page();
public ControlOnDisk(string path)
{
var o = pageHolder.LoadControl(path);
c = (ControlType)o;
pageHolder.Controls.Add(c);
}
public string RenderStateless()
{
StringWriter output = new StringWriter();
// set up dumby context for use in rendering to email stream
StringBuilder emailMessage = new StringBuilder();
TextWriter tw = new StringWriter(emailMessage);
HttpResponse dumbyResponse = new HttpResponse(tw);
HttpRequest dumbyRequest = new HttpRequest("", "http://InsertURL.com/", ""); //dummy url requierd for context but not used
HttpContext dumbyContext = new HttpContext(dumbyRequest, dumbyResponse);
//HttpContextBase dumbyContextBase = new HttpContextWrapper2(dumbyContext);
dumbyContext.Server.Execute(pageHolder, output, false);
return output.ToString();
}
}

Use ASP.NET Resource strings from within javascript files

How would one get resx resource strings into javascript code stored in a .js file?
If your javascript is in a script block in the markup, you can use this syntax:
<%$Resources:Resource, FieldName %>
and it will parse the resource value in as it renders the page... Unfortunately, that will only be parsed if the javascript appears in the body of the page. In an external .js file referenced in a <script> tag, those server tags obviously never get parsed.
I don't want to have to write a ScriptService to return those resources or anything like that, since they don't change after the page is rendered so it's a waste to have something that active.
One possibility could be to write an ashx handler and point the <script> tags to that, but I'm still not sure how I would read in the .js files and parse any server tags like that before streaming the text to the client. Is there a line of code I can run that will do that task similarly to the ASP.NET parser?
Or does anyone have any other suggestions?
Here is my solution for now. I am sure I will need to make it more versatile in the future... but so far this is good.
using System.Collections;
using System.Linq;
using System.Resources;
using System.Web.Mvc;
using System.Web.Script.Serialization;
public class ResourcesController : Controller
{
private static readonly JavaScriptSerializer Serializer = new JavaScriptSerializer();
public ActionResult GetResourcesJavaScript(string resxFileName)
{
var resourceDictionary = new ResXResourceReader(Server.MapPath("~/App_GlobalResources/" + resxFileName + ".resx"))
.Cast<DictionaryEntry>()
.ToDictionary(entry => entry.Key.ToString(), entry => entry.Value.ToString());
var json = Serializer.Serialize(resourceDictionary);
var javaScript = string.Format("window.Resources = window.Resources || {{}}; window.Resources.{0} = {1};", resxFileName, json);
return JavaScript(javaScript);
}
}
// In the RegisterRoutes method in Global.asax:
routes.MapRoute("Resources", "resources/{resxFileName}.js", new { controller = "Resources", action = "GetResourcesJavaScript" });
So I can do
<script src="/resources/Foo.js"></script>
and then my scripts can reference e.g. window.Resources.Foo.Bar and get a string.
There's no native support for this.
I built a JavaScriptResourceHandler a while ago that can serve Serverside resources into the client page via objects where each property on the object represents a localization resource id and its value. You can check this out and download it from this blog post:
http://www.west-wind.com/Weblog/posts/698097.aspx
I've been using this extensively in a number of apps and it works well. The main win on this is that you can localize your resources in one place (Resx or in my case a custom ResourceProvider using a database) rather than having to have multiple localization schemes.
whereas "Common" is the name of the resource file and Msg1 is the fieldname. This also works for culture changes.
Partial Javascript...:
messages:
{
<%=txtRequiredField.UniqueID %>:{
required: "<%=Resources.Common.Msg1 %>",
maxlength: "Only 50 character allowed in required field."
}
}
In a nutshell, make ASP.NET serve javascript rather than HTML for a specific page. Cleanest if done as a custom IHttpHandler, but in a pinch a page will do, just remember to:
1) Clear out all the ASP.NET stuff and make it look like a JS file.
2) Set the content-type to "text/javascript" in the codebehind.
Once you have a script like this setup, you can then create a client-side copy of your resources that other client-side scripts can reference from your app.
If you have your resources in a separate assembly you can use the ResourceSet instead of the filename. Building on #Domenics great answer:
public class ResourcesController : Controller
{
private static readonly JavaScriptSerializer Serializer = new JavaScriptSerializer();
public ActionResult GetResourcesJavaScript()
{
// This avoids the file path dependency.
ResourceSet resourceSet = MyResource.ResourceManager.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
// Create dictionary.
var resourceDictionary = resourceSet
.Cast<DictionaryEntry>()
.ToDictionary(entry => entry.Key.ToString(), entry => entry.Value.ToString());
var json = Serializer.Serialize(resourceDictionary);
var javaScript = string.Format("window.Resources = window.Resources || {{}}; window.Resources.resources = {1};", json);
return JavaScript(javaScript);
}
}
The downside is that this will not enable more than one resource-file per action. In that way #Domenics answer is more generic and reusable.
You may also consider using OutputCache, since the resource won't change a lot between requests.
[OutputCache(Duration = 3600, Location = OutputCacheLocation.ServerAndClient)]
public ActionResult GetResourcesJavaScript()
{
// Logic here...
}
http://www.asp.net/mvc/overview/older-versions-1/controllers-and-routing/improving-performance-with-output-caching-cs
I usually pass the resource string as a parameter to whatever javascript function I'm calling, that way I can continue to use the expression syntax in the HTML.
I the brown field application I'm working on we have an xslt that transforms the resx file into a javascript file as part of the build process. This works well since this is a web application. I'm not sure if the original question is a web application.
use a hidden field to hold the resource string value and then access the field value in javascript
for example :
" />
var todayString= $("input[name=TodayString][type=hidden]").val();
Add the function in the BasePage class:
protected string GetLanguageText(string _key)
{
System.Resources.ResourceManager _resourceTemp = new System.Resources.ResourceManager("Resources.Language", System.Reflection.Assembly.Load("App_GlobalResources"));
return _resourceTemp.GetString(_key);
}
Javascript:
var _resurceValue = "<%=GetLanguageText("UserName")%>";
or direct use:
var _resurceValue = "<%= Resources.Language.UserName %>";
Note:
The Language is my resouce name. Exam: Language.resx and Language.en-US.resx

Resources