I want to send the variables itemId and entityModel to the ActionResult CreateNote:
public ActionResult CreateNote(
[ModelBinder(typeof(Models.JsonModelBinder))]
NoteModel Model, string cmd, long? itemId, string modelEntity)
with this javascript:
Model.meta.PostAction = Url.Action("CreateNote", new { cmd = "Save", itemId = itemId, modelEntity = modelEntity});
However, the url being send is
localhost:1304/Administration/blue/en-gb/Entity/CreateNote?modelEntity=Phrase&itemId=44
I want to send
localhost:1304/Administration/blue/en-gb/Entity/CreateNote?modelEntity=Phrase&itemId=44
How can I prevent Url.Action to put the & in front of the second variable that I want to send?
I didn't notice yesterday that you had & I thought that was the SO editor had changed that. Try wrapping your Url.Action() in a #Html.Raw() to prevent the Encode of &.
Or alternatively only Url.Action() the controller/action bit and pass the two parameters as post data rather than directly on the url, jQuery should sort out the &'s for you that way.
I think your problem is with Model.meta.PostAction - is that property a string?
If so then my guess would be that you're adding it to the page with either:
Razor: #Model.meta.PostAction
ASP view engine: <%:Model.meta.PostAction%>
Both of which automatically encode that string for you.
To fix it either use #Html.Raw()/<%= (both of which don't encode) or make the PostAction property an IHtmlString that knows that it's already been encoded:
string actionUrl = Url.Action("CreateNote", new { cmd = "Save", itemId = itemId, modelEntity = modelEntity});
Model.meta.PostAction = new HtmlString(actionUrl);
Related
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
I'm a new c# developer and I have a dropdownlist populated with string dates formatted like this: "Jul 2017". There can be as many as 12 entries in the list.
When a user selects a date, I want to pass that selection to a controller method, convert it to a DateTime format and then use that date for further processing.
How do I pass the user selection to the controller so it can be converted and used? I've included commented out code below to show how I want to do the conversion. Getting the date to the controller is my challenge.
I've looked at similar questions on this site and they all seem overly complex (perhaps due to my naivete), but I was hoping for a more streamlined solution.
Html View Code
#Html.DropDownList("selectList", Model.ReverseMonthsLists())
View Model Code
public IEnumerable<SelectListItem> ReverseMonthsLists()
{
var selectListItems = GetDates()
.Select(_ => _.ToString("MMM yyyy"))
.Select((dateString, index) => new SelectListItem
{ Selected = index == 0, Text = dateString, Value = dateString })
.ToList();
return selectListItems;
}
public static IEnumerable<DateTime> GetDates()
{
DateTime startDate = new DateTime(2017, 6, 1).Date;
var currentDate = DateTime.Now.Date;
int numberOfMonthsToShow = (currentDate.Year - startDate.Year) * 12 +
currentDate.Month - startDate.Month;
var dates = new List<DateTime>(numberOfMonthsToShow);
currentDate = currentDate.AddMonths(-1);
for (int i = 0; i < numberOfMonthsToShow; i++)
{
dates.Add(currentDate);
currentDate = currentDate.AddMonths(-1);
}
return dates;
}
Controller function
public ActionResult Report_Performance()
{
//var newDate = DateTime.Parse(strDate); //<- Use newDate as parameter value into aVar to replace date at the end of the string
var aVar = Models.Reporting.ListingStatsReportingViewModel.GetStats(userCurrentService.CompanyId.Value, Models.Reporting.DateTimePeriod.Monthly, DateTime.Now.Date.AddMonths(-1));
return this.View(aVar);
}
The normal way to get a value to a controller is for the user to post the page back to the server, e.g. via a submit button. When this happens, the controller's action method can receive the selected item as an argument and then do what it needs to do. So if you just want the user to submit the form, and allow the web site to render the next page based on the selected value (and a list that you compute based on that value), that is all you need to do.
On the other hand, perhaps you don't want the user to submit the page; you want a series of dates to be displayed within the page, or for the dates to be processed by code running in the browser. If that is the case, I would suggest you perform the computations in Javascript within the browser itself, thereby avoiding the need for a round trip. Nothing in your GetDates() method requires any server side data, so it's just a question of converting your c# code to Javascript code.
In some rare cases, you will want a UX element on the page to get updated immediately based on a server computation, without the page being posted. If that is what you want, you'll have to use the AJAX solutions the other posters have provided. It's much more complicated and much more work. If you don't need that, use one of the solutions I provided above.
You Can Use The OnChange EventHandler For The HTML Select Option
(The DropDownList ) To Start An Ajax Call To Your Controller , Simply Create a JavaScript Function That Preforms a Jquery Ajax Request Containing The User Selected Data To The Controller and Retrieve JSON From The Controller Using Return Json() Instead Of Return View() , Then Handle The Retrieved Data Using JavaScript , Your Controller Will Need To Accept a Parameter In Order To Receive The Data From The Ajax Request
function SendDataToController (TheDropDownName){
var DataToSend = $('#'+TheDropDownName).text();
// Or Pass `this` From The Html When Assigning The Event Listener
// and Do Something Like var DataToSend = this.text();
$.ajax({
url: "#(Url.Action("ActionName", "ControllerName"))",
data: DataToSend,
success: function(ResponseFromController){
//Do Stuff With Response
}
});
}
This Will Send The Data To Controller So You Should Receive It in A Parameter
public ActionResult MyAction (string DataToSend)
{
//Do Stuff With Data and Get a Json Object To Return
Return Json(JsonObject);
}
MVC Ajax Is Essential So You Should Learn It Before Tryin To Work On Any MVC Project, Also You Should Handle Request Error Using fail attr in The Ajax Setting But I Will Leave That To You
I am using cefSharp in my winForm application.
I want to pass a long json from my winform to the html page displayed by the cefSharp.
I tried to write the following:
Private WithEvents m_chromeBrowser As ChromiumWebBrowser
...
CefSharp.Cef.Initialize()
page = New Uri("www...")
m_chromeBrowser = New ChromiumWebBrowser(page.ToString)
Panel.Controls.Add(m_chromeBrowser)
...
Dim json as String = "[{code:1,name:a,val:0},{...}....]"
m_chromeBrowser.ExecuteScriptAsync("functionName('" & json & "');")
But I keep getting the following error:
Request-URI Too Long
Do you have any idea how to pass long json from winform to browser.
Thanks
Well, you would be better off exposing a .Net class to JavaScript by registering an AsyncJSObject, execute the class method from JavaScript and parse the return result.
Something like this:
public class CallbackObjectForJs {
public string getJson() {
return myJsonString;
}
}
... then register the class:
_webBrowser.RegisterAsyncJsObject(
"Browser",
new CallbackObjectForJs(),
BindingOptions.DefaultBinder);
... and finally call the method from Javascript and use a promise to get the result:
Browser.getJson().then((result) => {
var myJsonString = JSON.parse(result);
console.log(myJsonString);
});
You can read more about it here:
https://github.com/cefsharp/CefSharp/wiki/General-Usage#3-how-do-you-expose-a-net-class-to-javascript
Hope it helps!
I had an asp.net-mvc site and I have an issue where I had an "&" in my query string that I am building with javascript and then using ajax to my server. Something like this:
www.mysite.com/MyController/Load?Tag=M&Ms
when I passed this to my server using ajax, it was showing up as
Tag="M"
so, in my javascript code, I changed my code from this:
"Load?Tag=" + tag;
to:
"Load?Tag=" + encodeURIComponent(tag);
and this fixed my issue. My server code looks like this
public ActionResult Load(ProjectParams projectParams)
{
//go do stuff
}
where ProjectParams looks like this:
public class ProjectParams
{
public string Tag {get;set;}
}
So everything was great until I realized that making this change on the javascript side, had a knockon effect. I just ran into an issue where if I have spaces in my tag name, it shows up on the server as:
My%20Tag%20Name
instead of:
My Tag Name
what is the correct way to encode on the javascript side for a url querystring and ensure that it shows up properly on the serverside controller action
you can decode it easily with
Server.UrlDecode()
and you could do that on the setter
Have Controller:
public class MyController : Controller
{
[HttpGet]
public ActionResult MyAction(int iMode, string strSearch)
{
return View();
}
}
In my view I have a div with id=center
I execute the following code in javascript
url = "/MyController/MyAction?iMode=7&strSearch=as";
$('#center').load(url);
When debugger his the breakpoint in my action on first line, iMode variable shows proper value of 7, strSearch parameter arrives as null.
Any help/advice would be most welcome.
Just use the ampersand instead of &
url = "/MyController/MyAction?iMode=7&strSearch=as";
Thanks Innatepirate for the tip. Wasted enough time trying to figure out why controller is getting null values. Replacing & with ampersand did the trick. By the way I was doing the simple age old window.location.href = link and still had the problem. Probably its the MVC parsing and routing that is messing this up.