Using ASP.NET Resources in React - asp.net

I have an old MVC 4 project that uses ASP.NET Resources in Razor views for localization.
I.e in a Razor view you may see
Views/Register.cshtml:
#Resource(() => Local.TermsAndConditions
This will go off and fine
Resources/Register.resx
And find the 'TermsAndConditions' parameter with the correct culture.
Now I don't actually know how all of this works, I've never worked on a multi-lingual application before, but I know that these resx files don't even have the correct information - what actually happens is somehow we fetch these from what looks like a complicated set of SQL tables in the database, using a built ResourceCache class.
I am trying to re-write the front-end using React, but am struggling with how to keep the localization - there are hundreds of entries and I am pulling my hair out a little here.
The only solution I can think of, is to manually find all the keys that would be required to lookup at the top of the view, and send these off to a custom API that will process these values for me, but feel like that may cause a large overhead on my application!
Any ideas?

So I solved this by creating a simple API method
List<string, string> LocaliseStrings (List<string> keys)
{
// get UI culture
// look up translated string
// add to return list in KVP
}
This would be called on every front-end page before anything else, and return the strings necessary

Related

How to do .Net Web Api versioning/routing for an app client?

So there are several parts to this question.
The 2 example endpoints (in simplest form):
user/{id}/profile
movie/{id}/info
I expect to create 2 controllers (UserController & MovieController).
How do I implement a view area before controller name?
Both of these are what I would consider a view. Therefore I would like to append a "view" in the url before the controller, as both controllers ONLY supply views. I later expect to also have a user controller in a different place that does NOT return views.
However, ALL my endpoints should start with /api/.
i.e. I want this:
api/view/user/{id}/profile
api/view/movie/{id}/info
But how do I register an area (/view/) while using "custom routing" (i.e.: httpConfiguration.MapHttpAttributeRoutes())? Any examples of this I couldn't find?
Where should I put versioning?
The client is an app, and will require versioning, so that we can make changes to the methods without breaking old versions of the app.
We are unsure where it would be best to place the versioning, and how the placement affects the development of new versions (if it does so at all?).
Possibilities:
1. api/v1/view/user/{id}/profile
2. api/view/v1/user/{id}/profile
3. api/view/user/{id}/profile/v1
version the whole API. This would upgrade the whole API to a new version, even if we only required a single method/endpoint to make an app-breaking change.
Are there any advantages to this that I am not seeing?
version the area. Same as above, just slightly fewer controllers affected.
version the method. Seems like the simplest, as only the single changed method is affected. But the url is very ugly.
Does anyone have an example of versioning in an MVC or Web Api structure that doesn't upgrade the whole API, but still keeps a somewhat nice structure in their URLs?
I ended up using https://github.com/Microsoft/aspnet-api-versioning as suggested by NightOwl888.
1.
Made my 2 controllers extend another controller with a const field that defined the routeprefix that they should share:
protected const string RoutePrefix = "api/view/v{version:apiVersion}";
...
[RoutePrefix(RoutePrefix + "/user")]
2.
The placement of the /v1/ doesn't matter with this Library. And allowed for either updating the controller or individuals methods, as seen fit per case basis.

Do I need to worry about session state?

Hi all hope you can help.
I am primarily a windows developer (winforms and wpf/mvvm) and it's been 10 years since my last web application, so this is probably a daft question.
I have just redeveloped a customer satisfaction questionnaire and as I had to figure out this from scratch thought I would use MVC 3 and Razor.
The Questionnaire is a single page web site with a controller that looks something like this.
Function Index(BrandName As String, CaseID As Integer, EventID As Integer) As ActionResult
ViewData("Scores") = Scores
Dim questionnaire As New Questionnaire
questionnaire.CaseID = CaseID
questionnaire.EventID = EventID
questionnaire.BrandName = BrandName
//Get Some specific branding from the database
questionnaire.FullBrandName = "FullNameFromDatabaseTable"
Return View(questionnaire)
End Function
Function Save(questionnaire As Questionnaire) As ActionResult
If TryUpdateModel(questionnaire) Then
SaveQuestionnaireToDatabase(questionnaire)
Else
Return RedirectToAction("Index")
End If
Return View()
End Function
I have stripped out some database code and some stuff to get a signed image url as i don't think its relevant.
I am not sure I fully understand the magic that is happening between view and controller which is the real reason for my question.
This is going up into azure along with everything else, I am asking the question about session state because this will be load balanced accross two instances. No authentication is required to access the page as it can only be completed once.
Many Thanks
p.s I couldn't get vb style quotes to work so put in the c# one.
It doesn't look like you are doing anything that touches the session, so there's no concern about which server the post goes to. All the information to process the request is submitted with the form.
You can take a look here (specifically section titled Implementing Add New Product ) to remove some of the mystery of how form data is mapped back to server side information.
If you have any content that needs to be shared / accessed across instances, simply use the AppFabric Cache, which went live about two weeks ago. I provided a link in this SO answer. The nice thing is that you can use the cache provider with just a few lines of code to set up, then call Put() and Get() for serializable key/value pairs. When you set up the cache, you can also enable a custom asp.net session state provider with a simple web config change - the Azure portal will auto-generate the xml for you.

Is there a standard way to implement an Edit form for an object that uses collections in ASP.NET MVC2?

Given an extremely simple object with only fields, e.g.:
class Contact {
string firstName;
string lastName;
DateTime birthday;
...
}
When you add a strongly-typed View with view content "Create", you get a nice form with all the fields of your object that passes the form back to the controller, etc, and life is good.
However, when the object becomes slightly more complex, like say we want to store email addresses for Contacts (and of course a Contact can certainly have more than one email address):
class Contact {
string firstName;
string lastName;
DateTime birthday;
ICollection<EmailAddress> emailAddresses;
...
}
Now when you add the strongly-typed view with view Content "Create", you get the same form as before, and the collection is not represented in the form in any way.
So now you have a form which is complete with one exception: you would like to add a section where the user can enter in as many or as few email addresses as they like and have those wrapped up and passed to the Controller on submit.
Is there a standard best-practice way of doing this in ASP.NET MVC2? If so, what is it?
MVC3 handles this a lot better but as your using MVC2 take a look at Steve Sanderson's detailed post on Editing a variable length list, ASP.NET MVC 2-style.
Phil Haack's Model binding to a list also gives you further information on how the default MVC2 model binders handle lists
Well, conceivably you can have your entire view be
HTML.EditorForModel()
If you follow the answer I posted to How to display the content of asp.net cache? to allow the Editor to do a deep dive against your model.
That's not the optimal solution. Manipulating List data in MVC is HARD. Mostly because of years of ASP.NET development has left us so disjoint from the metal of the web that the concepts of editing a list client side is easily lost on us.
For working with lists, you will also most likely need to work with client templating to be able to add new elements and remove elements easily. This can be get very complex due to the fact MVC requires all lists to be indexed and follow numerically otherwise on post backs you will be missing items (aside: I feel this was a terrible design decision)
Now with this being said, I would recommend looking at the KnockoutJS and KnockoutMapping frameworks which with the combination of jQuery and jQuery templating will allow you to create a very rich client experience. This unfortunately will most likely be a very radical departure from your existing development style however I feel what Knockout brings to the table is revolutionary and will open up the web so much further to ASP.NET MVC developers.

ASP.NET Localized web site -- updating on the fly

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.

Is there any way to use XmlSiteMapProvider within WinForm/Console/VSTest application?

I wonder whether there is a workaround for using the standard XmlSiteMapProvider within a non asp.net application, like WinForm/Console or, in my case, VS Unit Test one.
The following code fails, because it cannot create a path to the .sitemap file inside a private GetConfigDocument method.
XmlSiteMapProvider provider = new XmlSiteMapProvider();
NameValueCollection providerAttributes = new NameValueCollection();
providerAttributes.Add("siteMapFile", "Web.sitemap");
provider.Initialize("XmlSiteMapReader", providerAttributes);
provider.BuildSiteMap();
I feel the right solution is to write another provider.
I do not see why not. It is just a provider that implements an interface. You may not need many of the features, but you can access the API for what it provides you. Your WinForms screens can simply use the Urls for identification so that you can determine your place in the hierarchy.
What you may have to do is create a custom implementation of the provider because it will use the HttpContext to get the Url of the current web request to identify current placement while you will need to get that value differently. That is what could be tricky because your WinForm application could be displaying multiple windows at time. If you know there is only one window showing at a time you could use a static value which is set prior to accessing the SiteMap API.
Now you have to question the value of using an API if you have to do all of the work. There may not be enough benefit to make it worthwhile.

Resources