What I'm trying to do here is to allow my user to select a path in a data server on a network, so that I could generate a configuration file.
I hope to be able to replicate the function of OpenFileDialog() on my asp.net page. However this function does not exist on asp.net, and I do know that there is this control in asp.net call FileUpload. But what I required here, is just the path/directory for the folder. I do not require my files to be uploaded.
How can it be done?
Doing this in a web application is tricky. You would have to enumerate the folders on the server that you want to browse (presumably this is the same server that's running the web application), and then present that hierarchy to the user to select a folder. If it's not too big a hierarchy, you could just enumerate the whole bunch up front, and display it in a tree. If it's big for that, you could use an Ajax approach: select the top-level folder, then send an Ajax request to get the next level, and so on.
To enumerate the folders, you'll need to walk the filesystem yourself. See http://msdn.microsoft.com/en-us/library/dd997370(v=vs.100).aspx for one way.
No, there is no inbuilt control for this. It is not a normal requirement cause most site don't let their users see their file structures.
Building a user control that does this will be simple though.
I suggest using a TreeView asp.net control, attached to your datasource where you have listed the files.
This sample on binding a treeview should get you started.
You can populate your data using
var path = Server.MapPath("/");
var dirs = Directory.[EnumerateDirectories][2](path);
var files = Directory.[EnumerateFiles][3](path );
Finally to make it look like a dialog, you could use the jQuery UI dialog component.
The solution I have found is, this is just for anyone looking for answer:-
protected void browse_Click(object sender, EventArgs e)
{
Thread thdSyncRead = new Thread(new ThreadStart(openfolder));
thdSyncRead.SetApartmentState(ApartmentState.STA);
thdSyncRead.Start();
}
public void openfolder()
{
FolderBrowserDialog fbd = new FolderBrowserDialog();
DialogResult result = fbd.ShowDialog();
string selectedfolder = fbd.SelectedPath;
string[] files = Directory.GetFiles(fbd.SelectedPath);
System.Windows.Forms.MessageBox.Show("Files found: " + files.Length.ToString(), "Message");
}
The asp.net site is a completely disconnected environment to your server. As other people have mentioned, to replicate an OpenFileDialog() you will need to look at the folder structure and present this to the user in the web/disconnected environment. In this case the user is abstracted from the actual file system... since this abstraction already occurs, it would be a good time to consider the route you're taking. It might be worth considering that a direct replication of the file system is not required, you could manage the "virtual" folder structure in the database with links/paths to files on disk are maintained there?
Related
I build my own cms using asp.net mvc 4, and I want make it multi language
I thought about make table in the database of those rows:
id, name, language, value
and then create a helper that check the correct language and then give the correct value of the name
#html.L("Newsletter.Title")
By the way, I hear about .resx files, so what will be the best way? (performance)
and is there a way to handle this files using the web instead of make it in the visual studio ?
I want add the ability to a user (who don't know what is .rest file, programming etc..) can add language and translate it in the web.
I think resx files are great to localize "static" resources like buttons, navigation, etc, but not really dynamic content like the text on a page. But it always depends what your CMS is used for. Almost every CMS I know saves the data in a database. It's just more flexible than a .resx file.
But by all means, DON'T build your own CMS. Why would you wanna do that? There are tons of highly optimized CMS's out there.
In terms of performance it's difficult to beat using resource files (.resx) as these are effectively XML files on the server - you don't have round trips to the database to fetch the localisation text.
The system uses keys with associated text values, and separate resx files for each supported locale.
In order to consume these strings you would use a strongly typed class like this-
<h1>#WebResources.Page_Title_String</h1>
<p>#WebResources.Intro_Paragraph</p>
This makes it easy to send your site for translation into different languages as all the strings are in one place and there are plenty of tools available to work with the files inside and outside of Visual Studio. It is even possible to translate the file using Bing to give your translator a head start.
As this is effectively an XML file, you can easily manipulate it with using Linq to XML to create a web interface to change the text if you want. I have seen at least a couple of commercial products which use this approach both for localisation and customisation of product text.
See ASP.NET Web Page Resources Overview and How to: Create Resource Files for ASP.NET Web Sites for more details for Resource Files.
In order to achieve the best performance you would have to mix-up Resource Files (for static contents) and localized DB strings (for dynamic, CMS-created contents).
You can easily do that using the ResourceFiles + LocalizationRoute + LocalizationAttribute GlobalFilter approach which I described in this guide on my blog.
Localization Route:
routes.MapRoute(
name: "DefaultLocalized",
url: "{lang}/{controller}/{action}/{id}",
constraints: new { lang = #"(\w{2})|(\w{2}-\w{2})" }, // en or en-US
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Localization Attribute:
public class LocalizationAttribute : ActionFilterAttribute
{
private string _DefaultLanguage = "en";
public LocalizationAttribute(string defaultLanguage)
{
_DefaultLanguage = defaultLanguage;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string lang = (string)filterContext.RouteData.Values["lang"] ?? _DefaultLanguage;
if (lang != _DefaultLanguage)
{
try
{
Thread.CurrentThread.CurrentCulture =
Thread.CurrentThread.CurrentUICulture = new CultureInfo(lang);
}
catch (Exception e)
{
throw new NotSupportedException(String.Format("ERROR: Invalid language code '{0}'.", lang));
}
}
}
}
As soon as you implemented that skeleton, your current Thread will have the proper localization set, so your localized Resource Files will be selected automatically. All you'll have to do is to query your DB for the most suitable localized content (if available) for the localization settings of the current thread.
I have a frustrating issue when trying to pass a custom object from 1 page of a web site to another. When I try to use the object from session on the page 2 it is null. I believe that my syntax is correct as when I take the code out of my larger solution and run it on it's own it works fine.
I am wondering if there are any settings in visual studio, aspx files, project properties that may be set on my project that may be causing this session object not to work?
Simplied syntax that I am using is;
on page1
Person p = new Person;
p.name = "john";
p.secondName = "doe";
Session["person"] = p.
Response.Redirect("Page2.aspx")
Page 2 on page load method
Person p = (person)Session["person"]
textbox1.Text = p.name;
textbox2.Text = p.Secondname;
As I said this code works fine on it's own but not as part of my larger works project. Any ideas on why this may not be working would be greatly appreciated
There are three possible options.
First one is that inside your larger project session state is disabled. Please visit Turn Off ASP Session State in Active Server Pages and IIS for more details.
Second option would be that exception occurs somewhere inside your application (separate thread) resulting in application restart and session state loose. You can check this by hooking to Application error inside Global.asax like this:
void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
}
The last option would be that session["person"] value is changed in other module or page.
Try code with,
Response.Redirect("Page2.aspx", false);
See as per your code if there is database connected then i suggest you to do whatever you want to on page1 and save it to db in single or multiple tables, depending upon the requirements. Now paas the id to page2 as querystring. Format looks like
Response.Redirect("~/page2.aspx?id=67");
where is the dynamic unique id from database. Now on page 2.aspx query on the id you have passed.
I created an area in Visual Studio which automatically adds the appropriate bits in the "Areas" directory. I renamed this to "Modules" but now when i navigate to /{area}/{controller/{action} it still looks for the view within the /Areas/{area}/Views/{controller/{action} directory and not the /Modules/{area}/Views/{controller/{action} directory. I would also like to be able to override the view for specific themes. Therefore i was wondering how i could customise the default view engine to look for the view in the following locations aswell:
/Themes/Default/Views/{area}/{controller}/{action}.cshtml
/Modules/{area}/Views/{controller}/{action}.cshtml
I'd really appreciate it if someone could help.
Thanks
As ASP.NET MVC source code is available, it is easy to answer these kinds of questions by looking at the source. If you look at the WebFormViewEngine class you can see the locations listed and it will be easy for you to inherit from this and customise them.
However, not going with the code by convention approach is just going to make your life harder so I'd advise living with the default locations.
Here's the code incase anyone is interested:
public class CustomRazorViewEngine : RazorViewEngine {
public CustomRazorViewEngine()
: this(null) {
}
public CustomRazorViewEngine(IViewPageActivator viewPageActivator)
: base(viewPageActivator) {
AreaViewLocationFormats = new[] {
"~/Themes/Default/Views/{2}/{1}/{0}.cshtml",
"~/Themes/Default/Views/{2}/Shared/{0}.cshtml",
"~/Modules/{2}/Views/{1}/{0}.cshtml",
"~/Modules/{2}/Views/Shared/{0}.cshtml"
};
AreaMasterLocationFormats = new[] {
"~/Themes/Default/Views/{2}/{1}/{0}.cshtml",
"~/Themes/Default/Views/{2}/Shared/{0}.cshtml",
"~/Modules/{2}/Views/{1}/{0}.cshtml",
"~/Modules/{2}/Views/Shared/{0}.cshtml"
};
AreaPartialViewLocationFormats = new[] {
"~/Themes/Default/Views/{2}/{1}/{0}.cshtml",
"~/Themes/Default/Views/{2}/Shared/{0}.cshtml",
"~/Modules/{2}/Views/{1}/{0}.cshtml",
"~/Modules/{2}/Views/Shared/{0}.cshtml"
};
}
}
Now just place the following in the Application_Start event in the Global.asax.cs file:
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomRazorViewEngine());
Hope this helps.
The code you posted is very similar to what I wound up doing a few months ago.
I also have a preprocessing step (run on-demand or at compile time) which finds all of the .cshtml files in the site folder hierarchy and adds their relative paths to a table in the database. The site caches that data on startup. The custom view engine then searches that list for views, and only checks the disk when it finds a match.
This performs very, very well. Avoiding disk access will probably only help if you're running a very busy site. Even though disk access is very slow, it's typically not a performance bottleneck and ASP.NET performs its own intelligent caching.
We have a set of code that is going to be used in both standalone ASP.NET and SharePoint. I'm wondering if there's any legitimate way to write conditional code in the CS file to detect whether SharePoint is present?
It needs to be able to run in or before OnPreInit, because based on this decision we'll be switching the MasterPageFile attribute, and that needs to be done early in the page lifecycle.
I suppose I can do something like checking for the existence of a "~/layouts" directory, etc. but there must be a better way to do this. And besides, who knows - for compatibility reasons (location of images, etc) we might actually adopt the SharePoint directory structure in the ASP.NET standalone mode.
It's okay to require the Microsoft.SharePoint.DLL even if it goes mostly unused when running standalone.
Thanks!
Since you are allowed to reference Microsoft.SharePoint:
using Microsoft.SharePoint;
// ...
if (SPContext.Current == null)
// Not running in SharePoint
else
// Running in SharePoint
Edit -- alternate approach taking NullReferenceException into consideration:
bool runningInSharePoint = false;
try
{
if (SPContext.Current != null)
runningInSharePoint = true;
}
catch (NullReferenceException e)
{
// SharePoint is not present on the system
}
The above assumes that the exception you mentioned is thrown when accessing SPContext, not earlier.
I wonder if you are better off not including the SharePoint dll in your straight ASP.NET code.
If you partial/sub class the SharePoint bit and include two build targets, you should be able to tack on the extra code needed for SharePoint without turding up your ASP.NET build.
I think I have a solution to this, but is there a better way, or is this going to break on me?
I am constructing a localized web site using global/local resx files. It is a requirement that non-technical users can edit the strings and add new languages through the web app.
This seems easy enough -- I have a form to display strings and the changes are saved with code like this snippet:
string filename = MapPath("App_GlobalResources/strings.hu.resx");
XmlDocument xDoc = new XmlDocument();
XmlNode xNode;
xDoc.Load(filename);
xNode = xDoc.SelectSingleNode("//root/data[#name='PageTitle']/value");
xNode.InnerText = txtNewTitle.Text;
xDoc.Save(filename);
Is this going to cause problems on a busy site? If it causes a momentary delay for recompilation, that's no big deal. And realistically, this form won't see constant, heavy use. What does the community think?
I've used a similar method before for a very basic "CMS". The site wasn't massively used but it didn't cause me any problems.
I don't think changing a resx will cause a recycle.
We did something similar, but used a database to store the user modified values. We then provided a fallback mechanism to serve the overridden value of a localized key.
That said, I think your method should work fine.
Have you considered creating a Resource object? You would need to wrap your settings into a single object that all the client code would use. Something like:
public class GuiResources
{
public string PageTitle
{
get return _pageTitle;
}
// Fired once when the class is first created.
void LoadConfiguration()
{
// Load settings from config section
_pageTitle = // Value from config
}
}
You could make it a singleton or a provider, that way the object is loaded only one time. Also you could make it smart to look at the current thread to get the culture info so you know what language to return.
Then in your web.config file you can create a custom section and set restartOnExternalChanges="true". That way, your app will get the changed when they are made.