How to pass an additional parameter to CascadingDropDown ServiceMethod? - asp.net

I have two chained CascadingDropDowns. Both are working fine.
The thing is that in the underlying web methods which are supplying values for DropDwonList I need read one additional parameter. This parameter is needed for setting up the default item for dropdownlist.
I do not know how to pass that parameter or read it.
I've read on the Internet about the ContextKey property. But I do not know how to acces it from the WebMethod.
I've tried to get to the session through HttpContext.Current.Session (hoping that I could extract some parameter from the session) but it seams that the Session is different for the WebPage and WebMethod.
So I am lost here, any ideas?

You need three things to get the ContextKey to work.
Set UseContextKey property on the CascadingDropDown to true
Change the method signature of your webmethod to accept the contextKey parameter:
public CascadingDropDownNameValue[] GetDropDownContents(
string knownCategoryValues, string category, string contextKey) { ... }
NOTE: The parameter has to be exact casing.
Set the ContextKey using JavaScript. The AJAX CascadingDropDown exposes getter/setter for this property in the DOM:
document.getElementById('idOfCDDL').set_contextKey('valueyouwant');
HTH.

Passing Additional arguments
Sometimes the action method which provides the JSON for the combobox may need additional arguments. Here is how to pass them to your action:
CopyPassing additional arguments to the action method
function onComboBoxDataBinding(e) {
e.data = $.extend({}, e.data, { customParam: "customValue"});
}

In your .cs file write:
cascadingdropdown1.contextKey=<parameter you need>
Then in the web method use that contextKey

Related

thymeleaf onclick parameter

I try to pass an object to th:onclick.
When I pass a string(afficherDetails() function), everything is ok
When I pass an object(afficherDetails2() function), in the called function the object seems ok but it is empty.
function afficherDetails(employee) {
console.log("afficher Details");
document.getElementById("detailledFirstNameDataLabelId").textContent = employee.firstName;
document.getElementById("detailledLastNameDataLabelId").textContent = employee.lastName;
document.getElementById("detailledAddressDataLabelId").textContent = employee.address;
document.getElementById("detailledTitleDataLabelId").textContent = employee.title;
document.getElementById("detailledManagerDataLabelId").textContent = employee.manager;
}
function afficherDetails2(name) {
console.log("afficher Details");
document.getElementById("detailledFirstNameDataLabelId").textContent = name;
}
<td><button th:data-parameter1="${employee}" th:onclick=" afficherDetails(this.getAttribute('data-parameter1')) ">details</button></label></td>
<!--td><button th:data-parameter1="${employee.firstName}" th:onclick=" afficherDetails2(this.getAttribute('data-parameter1')) ">details</button></label></td-->
</tr>
Is it a correct behavior ? Can't we pass a complex object and we can only pass simple object?
thanks for your answer
Short answer:
You can pass a complex object to a HTML attribute - but it will be reduced to a string by the object's toString() method.
Therefore, in your case, an attempt to do the following in JavaScript...
var something = employee.firstName;
...will do nothing because the function is passed a string not an object - and therefore employee.firstName will be undefined in JavaScript.
Longer answer:
Bear in mind a couple of points:
A HTML attribute expects to contain a string:
<button th:data-parameter1="SOME VALUE IN HERE" ... >
So, the attribute data-parameter1 will be populated by Thymeleaf using a string.
All Thymeleaf processing happens on the server. Thymeleaf removes all its processing directives from the template and replaces them with valid HTML. Your JavaScript does not have access to the original Java object - just to whatever representation of that object was added to the HTML by Thymeleaf.
Let's assume you use something such as:
th:data-parameter1="${employee.firstName}"
Assuming employee.firstName evaluates to a string (John) then that is what Thymeleaf will use to produce this:
data-parameter1="John"
But if you try this:
th:data-parameter1="${employee}"
Assuming employee is your custom Java bean, then Thymeleaf will call its toString() method to use as the string.
If you have not defined a toString() method in your Employee class, then the underlying Object.toString() method will be used - and you will see something like the following - a string representation of the unique object, based on the object's name and hash code:
data-parameter1="org.yourpackage.Employee#bcb8097"
You can provide your own implementation of toString() in your Employee class to provide more useful information. But it has to be a string which can be placed in a HTML attribute.
For example, if you pass an ArrayList to the button:
List<String> names = Arrays.asList("John", "Mary");
and:
th:data-parameter1="${names}"
then your HTML button will contain this:
data-parameter1="[John, Mary]"
because [John, Mary] is the result of how ArrayList has implemented its toString() method.
You can send a certain Java objects directly to JavaScript - see JavaScript serialization. But that is probably off-topic for this question.
One extra note: In the following:
th:onclick="afficherDetails(this.getAttribute('data-parameter1'));"
You are using th:onclick - but there are no Thymeleaf expressions in the attribute, so there is nothing for Thymeleaf to process. You can just use:
onclick="afficherDetails(this.getAttribute('data-parameter1'));"

Replace default client side validation by custom one in ASP.NET MVC

I have a view model containing a DateTime property, for which I want to provide a text box using using a custom format (only month and year, "MM.YYYY"):
public class MyModel {
public DateTime? DateField {get; set;}
}
Formatting the value for the TextBox is easy (using the format string). I also have implemented a custom model binder to do the conversion and this works fine.
I still have a problem with client side validation: I can implement a custom validator deriving from ValidationAttribute which implements IClientValidatable and set up the corresponding jquery.validate adapters etc.
But MVC still adds the "default" validation attribute data-val-date (in addition to my custom validation attribute data-val-monthyeardate) to the input field, so the default check still applies and the input "MM.YYYY" is rejected.
Is there any way to suppress the default client side validation for a data type and replace it with a custom one (instead of "adding" the custom one)?
Since the framework doesn't let you override the real type with some custom attribute or even override the ModelMetadataProvider for specific types, you'll have to register your own global ModelMetadataProvider that fools the validator to think it's actually a string.
Something like:
public class MyModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
{
if (attributes.OfType<ExcludeCharAttribute>().Any())
modelType = typeof (String);
return base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName); ;
}
}
Register it using:
ModelMetadataProviders.Current = new MyModelMetadataProvider();
Still, since the core problem is a client-side problem, I would deal with it purely with client-side code. In your monthyeardate adapter you can force removal of the date validation (I can provide an example if you'll share your monthyeardate code).
See MSDN
This is hacky but one simple thing you could do is add:
$(function () {
$.validator.methods.date = function () { return true; };
});
So that the default data-val-date always returns true along with firing your custom date validation.
I know that this is a little older, and just in case someone doesn't think about it (and since I cannot leave comments yet), to enhance #AlexC response, you can add validation to to that statement.
For instance, I use moment.js for date validation (moment.js), and this allows you to add your own validation rules.
if (moment(a, "M/YYYY").isValid() || moment(a).isValid())
{
return true;
}
This will check to see if it is a regular date, and also in this case, if the date is in "M/YYYY" format. If one of these are true, it accepts the validation.

mvc default model binder only binds first word of a string?

Why does my action method only bind the first word of a string I pass into it using a query string?
For example, in jquery, I build a queryString from the results of an ajax call:
success: return(resultData){
var queryString = "?ok=true&message=" + resultData.message;
}
Then I try to load a view into a dialog by calling a controller and passing the queryString
$dialogHandle.load("/Account/RegisterStatus" + queryString, function() { ... });
At this point the queryString correctly hold an entire message. However if I break in my controller:
public ActionResult RegisterStatus(bool ok, string message)
{
//break here
}
I notice that ok binds correctly but message only contains the first word of the error message passed in.
How can I pass a sentence as one string parameter?
Is there a better way to do this, without query string?
EDIT: hmm now that I think about it does make sense since urls cant have space but then how do I accomplish this... is there a specific word delimiter in the default model binder?
It's all about URL escaping: escape("It's me!") // result: It%27s%20me%21
Do that around your resultData.Message and it should work better. For debugging purposes, use Fiddler2 or some Web Inspector to see what request is being send. This is really valuable when you are debugging AJAX...
And of course, do the reverse in C#: HttpUtility.UrDecode Method (String)

DataMember Emit Default Value

I have a .Net Web Service function that can accept one string.
That function will then serialize that string to JSON, but I only want to serialize it if it's value is not "".
I found these instructions:
http://msdn.microsoft.com/en-us/library/aa347792.aspx
[DataContract]
public class MyClass
{
[DataMember (EmitDefaultValue=false)]
public string myValue = ""
}
Unfortunatelly I can not hide the myValue from the serialization because "" is not the .Net default value for a string (how dumb is that!)
One of two option ocurred
On the web service have some kind of attribute that sets the "" to null
Have some condition on the class
I would prefer the 1st because it makes the code cleaner but an opinion would be great.
Thanks
You can explicitly set what the default value is (for the purposes of serialization) using the DefaultValueAttribute class:
[DataContract]
public class MyClass
{
[DataMember (EmitDefaultValue=false)]
[DefaultValue("")]
public string myValue = ""
}
I think you have at least a couple of options here. It's extra work but worth it.
You can encapsulate the string in a reference type. Since reference types are null if not present, that lets you know right away if a string was present or not (because the encapsulating reference type would be either non-null or null, if the string is non-empty or not.)
A final option you have is to add an extra complementary variable (perhaps a boolean) that is set on OnDeserializing/OnDeserialized/OnSerializing/OnSerialized and use this to track whether or not something was actually present on the wire. You might, for example, set this complementary variable to true only when you're actually serializing out a non-empty string and similarly

Cannot get session in webmethod in asp.net

I just find that the problem is not related to the webmethod.
It is caused by another problem.
I set the Session["PhotoId"] in a normal aspx.
But I can't retrieve value in the webMethod of the aspx page.
[WebMethod(EnableSession=true)]
public static string Submit(string data1, ...)
{
string test = HttpContext.Current.Session["PhotoId"]; // test is null
}
What should I do?
As I see, everything should be fine here.
As far as HttpContext.Current.Session is not null, session state is supported here.
Please ensure, that you set Session["PhotoId"].
You can test whether it is the same session by examining
HttpContext.Current.Session.SessionID
in both normal ASPX and WebMethod.
You should use ToString() method to use session as a string.
[WebMethod(EnableSession=true)]
public static string Submit(string data1, ...)
{
string test = HttpContext.Current.Session["PhotoId"].ToString();
}

Resources