Localize javascript messages and validation text - asp.net

I'm working on a web project that is multilingual. For example, one portion of the project involves some custom google mapping that utilizes a client-side interace using jquery/.net to add points to a map and save them to the database.
There will be some validation and other informational messaging (ex. 'Please add at least one point to the map') that will have to be localized.
The only options I can think of right now are:
Use a code render block in the javascript to pull in the localized message from a resource file
Use hidden fields with meta:resourcekey to automatically grab the proper localized message from the resource file using the current culture, and get the .val() in jquery when necessary.
Make a webservice call to get the correct message by key/language each time a message is required.
Any thoughts, experiences?
EDIT:
I'd prefer to use the .net resource files to keep things consistent with the rest of the application.

Ok, I built a generic web service to allow me to grab resources and return them in a dictionary (probably a better way to convert to the dictionary)...
<WebMethod()> _
<ScriptMethod(ResponseFormat:=ResponseFormat.Json, UseHttpGet:=False, XmlSerializeString:=True)> _
Public Function GetResources(ByVal resourceFileName As String, ByVal culture As String) As Dictionary(Of String, String)
Dim reader As New System.Resources.ResXResourceReader(String.Format(Server.MapPath("/App_GlobalResources/{0}.{1}.resx"), resourceFileName, culture))
If reader IsNot Nothing Then
Dim d As New Dictionary(Of String, String)
Dim enumerator As System.Collections.IDictionaryEnumerator = reader.GetEnumerator()
While enumerator.MoveNext
d.Add(enumerator.Key, enumerator.Value)
End While
Return d
End If
Return Nothing
End Function
Then, I can grab this json result and assign it to a local variable:
// load resources
$.ajax({
type: "POST",
url: "mapping.asmx/GetResources",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: '{"resourceFileName":"common","culture":"en-CA"}',
cache: true,
async: false,
success: function(data) {
localizations = data.d;
}
});
Then, you can grab your value from the local variable like so:
localizations.Key1
The only catch here is that if you want to assign the localizations to a global variable you have to run it async=false, otherwise you won't have the translations available when you need them. I'm trying to use 'get' so I can cache the response, but it's not working for me. See this question:
Can't return Dictionary(Of String, String) via GET ajax web request, works with POST

I've done this before where there are hidden fields that have their values set on Page_Init() and Page_Load() with the appropriate values from the global and local resource files. The javascript code would then work with those hidden values.
Code Behind
this.hfInvalidCheckDateMessage.Value = this.GetLocalResourceObject("DatesRequired").ToString();
Page.aspx
$('#<%= btnSearch.ClientID %>').click(function(e) {
if (!RequiredFieldCheck()) {
var message = $("#<%= hfInvalidCheckDateMessage.ClientID %>").val();
alert(message);
e.preventDefault();
$("#<%= txtAuthDateFrom.ClientID %>").focus();
}
});
Disclaimer... Not sure if this was the best route or not, but it does seem to work well.

I've implemented a modified version of the solution described here: http://madskristensen.net/post/Localize-text-in-JavaScript-files-in-ASPNET.aspx
I changed it to allow for multiple resource file names, if the need for it arises, by changing the regular expression and by using the HttpContext.GetGlobalResourceObject method to retrieve the resource string.

I use this technique. It makes it easy for anyone with little coding experience to edit the phrase JavaScript file.
var lang = 0 // 0 = english, 1 = french
var phrases=[]
phrases["plans"] = "Rate Plans and Features|Forfaits et options").split("|")
then you output it as:
phrases["plans"][lang]
...add more columns as required.

Related

Can we call ASP.NET webservice without soap envelop? Like a simple REST api

Can we create a simple post method in ASP.NET web service which runs like a REST API method?
Because I don't want to provide an envelop for post and get request.
Can anyone provide a solution for this?
Not only can you do this, but in fact, if you create a web method in .net, right out of the box:
It can accept soap 1.1, 1.2 - no extra code on your part
It can accept a rest call - even json data - no extra code on your part
It can accept a plane jane URL (again rest) call - no extra code on your part
So, in fact, you get all 3 of the above - in fact the above counts as 4, since your ajax call can use (data) or the URL to pass the information.
Say, I add a I create a web service page like this:
Do note, you don't HAVE to crate a web service page, you can drop into a EXISTING page a function (returns values), or drop in a sub into that page. As long as you ta the function/sub with WebMethod(), then you are good to go.
So, with above page, lets add a simple function. It will take a paramter FirstName, and LastName, and return the full name.
So, we have this code in the above web service page:
<WebMethod()>
Public Function GetName(FirstName As String, LastName As String) As String
Dim sResult As String = ""
sResult = FirstName & " " & LastName
Return sResult
End Function
Above is VERY simple.
So, you can use jQuery, and call this method via post like this:
<asp:Button ID="cSoap" runat="server" Text="Soap Example"
OnClientClick="webcalltest();return false" />
<script>
function webcalltest() {
var First = 'Albert'
var Last = 'Kallal'
var url = '../WebService1.asmx/GetName'
$.ajax({
type: "POST",
url: url,
dataType: "json",
data: JSON.stringify({ FirstName: First, LastName: Last }),
contentType: "application/json; charset=utf-8",
success: function (msg) {
alert(msg.d)
},
error: function (msg) {
alert("Failed: " + msg.status + ": " + msg.statusText);
}
});
As noted, that web method will also accept soap calls.
And you can even skip the headers (in the above post), and toss out a 100% plane jane REST call - just the URL, say like this:
<asp:Button ID="Button2" runat="server" Text="Soap Example"
OnClientClick="webtest2();return false" />
<script>
function webtest2() {
var First = 'Albert'
var Last = 'Kallal'
var url = '../WebService1.asmx/GetName?FirstName=' + First + '&LastName=' + Last
$.get(url, function (data, status) {
alert($(data).find('string').text())
alert("Data: " + data + "\nStatus: " + status);
})
}
</script>
So, in above, we just used the URL for the rest call. (and did not set up any headers, or even a soap xml record). So, just keep in mind, even older legacy soap methods in most cases can be passed and consume JSON data - and you in general don't have to re-write or even change the web methods.
And as above shows, you can just feed the URL with the parameters, and not pass any headers at all - let alone the soap ones.

save some data [into the database] every few seconds using Ajax

I have a page where i have to save some data [into the database] every few seconds.This is similar to how gmail or stackoverflow saves a draft every few seconds. I am using jQuery Ajax to achieve this. Following is my Ajax call :
Question: Is this the correct way to do this? I am not comfortable with opening and closing the connection every few seconds.
function ShowHtml() {
var SaveStoryForEditing = '<%= Page.ResolveUrl("~")%>Webservices/WebService.asmx/SaveStoryForEditing';
$('#savedata').html($('#InPlaceEdit').html());
$("#InPlaceEdit").find("textarea").each(function (idx) {
$("#savedata").find("textarea").eq(idx).text($(this).val());
});
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: SaveStoryForEditing,
dataType: 'json',
async: false,
data: "{'StoryEditId':" + $('#hfStoryEditID').val() + ",'AccountId':" + $('#hfAccID').val() + ",'StoryHtml':'" + $('#savedata').html() + "'}", // Page parameter to make sure we load new data
success: function (data) {
var myObject = eval('(' + data.d + ')');
$('#InPlaceEdit').effect("highlight", { color: "#ff0000" }, 1000);
$('#savedata').html('');
AutoSave();
},
error: function (result) {
AutoSave();
alert(JSON.stringify(result));
}
});
};
function AutoSave() {
setTimeout("ShowHtml()", 30000);
};
This is the function i am calling from the webservice:
Public Shared Function SaveStoryForEditing(ByVal StoryEditId As Integer, ByVal AccountId As Integer, ByVal StoryHtml As String) As Object
Dim db As SqlDatabase = Connection.Connection
Dim scalar As Object
Dim cmdIf As SqlCommand = CType(db.GetSqlStringCommand("UPDATE StoryEdit SET StoryHtml=#StoryHtml WHERE AccountID=#AccountID AND StoryEditID=#StoryEditID"), SqlCommand)
db.AddInParameter(cmdIf, "AccountID", DbType.Int32, AccountId)
db.AddInParameter(cmdIf, "StoryEditID", DbType.Int32, StoryEditId)
db.AddInParameter(cmdIf, "StoryHtml", DbType.String, StoryHtml)
scalar = db.ExecuteNonQuery(cmdIf)
Return scalar
End Function
This is my connection object class:
Imports Microsoft.Practices.EnterpriseLibrary.Data.Sql
Imports System.Data.SqlClient
Public Class Connection
Public Shared Function Connection() As SqlDatabase
Dim db As SqlDatabase = New SqlDatabase(System.Configuration.ConfigurationManager.ConnectionStrings("TripNestConStr").ConnectionString)
Return db
End Function
End Class
I believe this is not a good way to go. You're creating (probably) unnecessary traffic. If you really need such functionality, I'd at least consider some kind of mechanism that will track changes and execute ONLY if something has changed after the last server call. You don't really need to send a request to the server and access the database, if the data haven't changed.
Just some idea for you to consider, it all depends on your specific situation and needs.
I am thinking why don't use the hidden field kind of flag to check if the value is updated or not. On keypressup of the textarea you can set the hidden value as true. In the autoSave method check the value of the hidden field , if it is true then only go back to server. Once you picked the value update it back to false again . So that it will help you to save some time overload . Another way is rather than saving true false , you can also save the time stamp of change and have a global variable in javascript which will tell the last time you have updated in the database. If the global value is in past compare to current update in the hidden field , you need to sync.

autocomplete with asp.net generated json

I have the folowing script which does not seem to work. The aspx page returns json similar to the json in the script below which has been commented out. If I stick that json directly into the source as an array, it works perfectly.
But as soon as I try to use the script below, I get no error messages or anything, nothing happens when i type into the autocomplete field.
$(document).ready(function(){
$('#button').click(function() {
alert($("#txtAllowSearchID").val());
});
//var $local_source = [ {id:0,value:"c++"}, {id:1,value:"java"}, {id:2,value:"php"}, {id:3,value:"coldfusion"}, {id:4,value:"javascript"}, {id:5,value:"asp"}, {id:6,value:"ruby"} ];
$("#txtAllowSearch").autocomplete({
source: function(request, response) {
$.ajax({
type: "POST",
url: "test_array.aspx",
data: "{'prefixText': '" + $('#txtAllowSearch').val() + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data) {
response(data.d);
},
failure: function(errMsg) {
$('#errMessage').text(errMsg);
}
});
},
select: function (event, ui) {
$("#txtAllowSearch").val(ui.item.value); // display the selected text
$("#txtAllowSearchID").val(ui.item.id); // save selected id to hidden input
}
});
});
EDIT: I think the problem is in the aspx page:
objSQLCommand = New SqlCommand("select id, value from table1 where value like '%#prefixText%'", objSQLConnection)
objSQLCommand.Parameters.Add("#prefixText", SqlDbType.VarChar, 255).Value = "ing"
I believe that you have to make the source of the ajax call to a web service, which in your case seems to be a Page Method. So if you have a function in your code behind page look like this:
public static List<string> GetData(string prefixText){ }
You would need to decorate that method with [WebMethod] from the System.Web.Services namespace.
So it would finally look like:
using System.Web.Services;
...
[WebMethod()]
public static List<string> GetData(string prefixText){ }
HTH
EDIT: also you would need to update your ajax call to look like this for the source:
source: 'test_array.aspx/GetData'
It looks to me like the issue might be the source function. When you make the ajax call, it is done asynchronously. So, the function kicks off the ajax call and continues, which returns nothing for the source.
I discovered this when I was doing loading screens. If I put the close for the loading screen after the ajax call, the loading screen would not appear. I had to move it inside the ajax call success and error events to get it to appear and disappear correctly.
Your source should just be a reference to the url
source: "test_array.aspx",
From the documentation:
The datasource is a server-side script
which returns JSON data, specified via
a simple URL for the source-option.

Find a control by String from asp.net Web service

Well since it seems relatively difficult to send the object of a WebControl over JSON using jquery.ajax() I've decided to send the name of the control as a string because I know how to do that. Then I promptly realized that, from a web service, I don't actually know how to search for a control by ID name. Since its a service I can't seem to get Control.FindControl() to work so does anyone have ideas or suggestions? All I'm trying to do is call a databind() on my radcombobox.
Thanks in advance!
For any of you that knows anything about asp.net/rad controls - I'm basically updating a database and want the radcombobox to be in sync with that database again after adding something, before I autoselect what was just added. Other than databind do i have to call anything to refresh that list?
Thanks again!
The way i would go in this case is the following:
Make some change on the data set
Make a call to the web service to update the html page
On the service method - i would load the same control and data bind it with the updated data set like this:
// create standard webform
Page page = new Page();
HtmlForm form = new HtmlForm();
page.Controls.Add(form);
// prepare for rendering
StringBuilder html = new StringBuilder();
StringWriter tw = new StringWriter(html);
HtmlTextWriter hw = new HtmlTextWriter(tw);
// load the control to render
Control control = page.LoadControl("relativeControlPath");
TypeOfYourControl myControl = (TypeOfYourControl)control;
myControl.DataSet = GetUpdatedDataSet();
myControl.DataBind();
form.Controls.Add(myControl);
// render
HttpContext.Current.Server.Execute(page, hw, false);
// pack the output as JSON
result.Add("html", html.ToString());
JavaScriptSerializer ser = new JavaScriptSerializer();
string json = ser.Serialize(result);
return json;
4. When the ajax call receives a response from the previous step, all i have to do i s to replace the current dom element with the newly rendered one:
$.ajax({
type: 'POST',
contentType: 'application/json; charset=utf-8',
url: "webServiceUrl",
data: "{'if you need a specific params to identify nature of your control':'" + data + "'}",
dataType: 'json',
success: function(result) {
var output = eval('(' + result.d + ')');
$("oldNode").remove();
$("parentNode").append(output.html);
}
});
This approach is generally suitable when you are dealing with composite controls and cannot control or change their behavior.
But for general async update methods i would recommend more lightweight methods like sending serialized data over JSON and using something like jQuery templates on client side for markup generation.

ASP NET MVC Server Response to a basic ajax request

We have to make an ASP.NET MVC or ASP.NET application for basic ajax navigation in Customer.html of Notrhwind.mdb.
We have this 3 things:
A pure HTML/JavaScript form having HTML input text tags, one for each field of Customers table.
We have also 2 navigation buttons: NextRecord and PrevRecord having at OnClick() event : clientGetRecord(NextOrPrev)
A javascript ajax clientGetRecord function, something like this:
function clientGetRecord(NextOrPrev) {
var oXMLHTTP = new ActiveXObject("Microsoft.XMLHTTP");
var sURL = "ServerGetRecord.aspx?ID=" + NextOrPrev;
oXMLHTTP.open( "POST", sURL, FALSE );
oXMLHTTP.send();
var sResult=oXMLHTTP.responseText;
var aRecord = sResult.split(";");
document.getElementById('CustomerID').value = aRecord[0];
document.getElementById('CompanyName').value = aRecord[1];
document.getElementById('ContactName').value = aRecord[2];
document.getElementById('Adress').value = aRecord[3];
//... and so on ...
};
We must have something like a ServerGetRecord controler function which returns to the clientGetRecord function, a simple string containing the current record fields values separated by comma and using classic ADO database handling.
The question is : How to program and invoke the ServerGetRecord function? Can i have a VB code example of ServerGetRecord function (or ASPX, or ASHX, or something else?..) ?
Don't have any VB smaples for you, but you can create a controller (asp.net mvc) that returns a JsonResult. You get your data from the DB and build the JsonResult object to return.
Then on your client use jQuery to call the controller and get the results as json format.
This post can help you get started: Link
Hope this helps

Resources