Pass parameter values from JQuery to VB.Net Function - vb.net

I have here a vb.net function which accepts 2 parameters and the values that will be passed here will be coming from my jquery code. Is it possible to pass the values from jquery to vb.net? I've already read some solutions but they point out that the vb.net method should be a webmethod. In my case, the vb function is not a web method so that strikes that out. Below are some snippets of my code. Hope you could help me on this.
JQuery code
$('#TextBox_PRVNo').keypress(function (event) {
if (event.keyCode == '13') {
//basically, pass values from textbox 1 and textbox 2 to VoucherNotClaimed() method
}
});
VB.Net code
Private Function VoucherNotClaimed(ByVal strVoucherType, ByVal strPRVNo) As Boolean
' TODO: Search in database
Return True
End Function

You don't need a web service to decorate your methods with the WebMethod attribute. If you do it on a regular page, you create a so-called page method. In a nutshell:
Create a public static method in your page, decorated with the WebMethod attribute:
<WebMethod()> _
Public Shared Function VoucherNotClaimed(ByVal strVoucherType, ByVal strPRVNo) As Boolean
' TODO: Search in database
Return True
End Function
Add a ScriptManager to your ASPX page and set its EnablePageMethods property to True. Also, make sure your web.config is set up properly.
Call your method with JavaScript:
var claimed = PageMethods.VoucherNotClaimed(voucherType, prvNo);
You can find a more detailed explanation in the following MSDN article:
Exposing Web Services to Client Script (Section Calling Static Methods in an ASP.NET Web Page)
Note that this is the classic way to do it. With JQuery, it is also possible to call the page method without a ScriptManager; a quick Google search for page method jquery yields a huge amount of blog entries going into every possible detail.

Related

Extend Office JavaScript API with own Browser Control

I'm trying to write a VSTO-Add-In with a System.Windows.Forms.WebBrowser-Control enabling something similar to the Office-JS-Add-In model.
The WebBrowser-control would show some HTML/JS-Page and be able to call C#-functions in the VSTO-Add-In from JavaScript via window.external and the ObjectForScripting-property of the WebBrowser-object.
That is in JS the call would be
window.external.DoFancyStuffToMyDocument(withTheseParams)
while there had to be some
class MyFunctionProxy() {
public void DoFancyStuffToMyDocument(string theParam) {
//code here
}
}
in the C#-Code an this would be attached to the WebBrowser
myWebBrowser.ObjectForScripting = new MyFunctionProxy();
So far so good. Now comes the catch. I want my HTML/JS-Code be able to also utilize the office.js code and functions like
Word.run(function (context) {
var thisDocument = context.document;
var range = thisDocument.getSelection();
range.insertText('"Hitch your wagon to a star."\n', Word.InsertLocation.replace);
//...
}
Does anyone see a way of getting this to work?
My initial guess was that the OfficeJS-taskpane-add-ins in Word on-prem use some some similar methode as above with a class derived from WebBrowser and the appropriate ObjectForScripting. This would then suggest that there must be a (hopefully accessible) class which is assigned to the ObjectForScripting-property handling the function calls from office.js. Then I could proxy this ObjectForScripting-class and add my own functions like 'DoFancyStuffToMyDocument()'.

What are DShellFolderViewEvents and DShellFolderViewEvents_Event?

The names make it sound like some sort of event handler.
Both were identified as an interface from Shell32 using the code below:
I can't find either of these in the MSDN libraries. Google returned some pages with code where they appeared, but I didn't see anything that really described the interface.
Public Sub ListTypes()
Dim NS As String = "Shell32"
For Each t As Type In Assembly.GetExecutingAssembly().GetTypes()
If (t.IsClass Or t.IsInterface) And t.Namespace = NS Then
Debug.Print(t.Name)
End If
Next
End Sub
Based on the definition in ShlDisp.h it appears to simply be a thin wrapper around IDispatch with a different GUID.
MIDL_INTERFACE("62112AA2-EBE4-11cf-A5FB-0020AFE7292D")
DShellFolderViewEvents : public IDispatch
{
};
It seems to be used in obtaining event notification from the shell - Raymond Chen's blog has some example code.

WebAPI REST - not calling correct controller when using multiple parameters

Having a bit of an issue getting the Web API to call the correct handler when I pass parameters with my Get request.
My basic handler is this:
Public Function GetAllASTM05Report() As IEnumerable(Of ASTM05Report)
Return repository.GetAll()
End Function
And that returns all records just fine.
But now I want to add this:
Public Function GetASTM05ReportWithSearch(sortField As String, searchOrder As String, searchField As String, searchValue As String) As IEnumerable(Of ASTM05Report)
Return repository.GetAllWithSearch(0, 25, sortField, searchOrder, searchField, searchValue)
End Function
But when I try this URI:
http://localhost/AdminAPI/api/astm05report?sortField=reportId&sortOrder=ASC&searchField=ReportID&searchValue=rr
I expect it to use GetASTM05ReportWithSearch() but it ends up going to GetAllASTM05Report().
If I remove GetAllASTM05Report() then I get an error: No HTTP resource was found that matches the request URI.
One person supposedly got it working by passing an object like this:
Public Function GetASTM05ReportWithSearch(<FromBody> values As SearchValues)
Return repository.GetAllWithSearch(0, 25, values.sortField, values.searchOrder, values.searchField, values.searchValue)
End Function
But I got an error: Multiple actions were found that match the request
If I remove GetAllASTM05Report(), GetASTM05ReportWithSearch() does fire, but values is nothing.
I have not changed the default routing tables and my client JS does not like the true REST syntax like:
http://localhost/AdminAPI/api/astm05report/reportId/ASC/ReportID/rr
So I do not want to explore solutions which require such routing table mods.
Help! What am I doing wrong?
EDIT: Jon Susiak called it - misnamed parameter. Embarrassing!
Thanks,
Brad

Deserialize object content manually in Web-API OData

When using WCF Data Services Client to communicate with my OData API, I occasionally need to use the
AddRelatedObject method of System.Data.Services.Client.DataServiceContext
This generates a POST to the endpoint that looks like:
http://base_url/odata/Entity(key)/NavigationProperty
The content of the http request is the serialized NavigationProperty entity.
Since a post to this URL is unmapped in a default odata controller, I wrote a new EntitySetRoutingConvention class:
Public Class AddRelatedObjectRoutingConvention
Inherits EntitySetRoutingConvention
Public Overrides Function SelectAction(odataPath As Http.OData.Routing.ODataPath, controllerContext As Http.Controllers.HttpControllerContext, actionMap As ILookup(Of String, Http.Controllers.HttpActionDescriptor)) As String
If controllerContext.Request.Method = Net.Http.HttpMethod.Post Then
If odataPath.PathTemplate = "~/entityset/key/navigation" Then
If actionMap.Contains("AddRelation") Then
Return "AddRelation"
End If
End If
End If
Return Nothing
End Function
End Class
I added this to the default routing conventions list and passed it to the MapODATARoute routine.
In my base controller I implemented AddRelation, and it is called perfectly.
From this I am able to get the odatapath, and parse it to determine the types and keys that are needed.
The problem I am having, is that once I know that my parent entity is a Tenant with a key of 1, and that the NavigationProperty of Users in the Tenant entity is a User entity, I can not figure out how to manually call an odatamediatypeformatter to deserialize the http content into the User entity so that I can then add it to the Tenants Users collection.
I have reviewed the OData source in an effort to find out how to the Web-API pipeline calls and deserializes the entity but have been unable to find the point at which the OData library takes the http content and turns it into an entity.
If anyone has an ideas to point me in the right direction, I will continue researching and update if I figure out more.
UPDATE 06/28/2013
Thanks to RaghuRam, I've been able to get closer. The problem I'm seeing is that the request.getconfiguration().formatters, or odatamediatypeformatters.create both seem to create type specific deserializers.
When I call ReadAsAsync I receive the error:
No MediaTypeFormatter is available to read an object of type 'User' from content with media type 'application/atom+xml'.
As the post shows above, the context of the controller is a Tenant, so I believe the formatters are typed to a Tenant and so can't deserialize the User.
I tried manually creating a formatter, _childDefinition is the EDM Type Reference from the navigation property of the odatapath. In this case a User.
Dim dser As New Formatter.Deserialization.ODataEntityDeserializer(_childDefinition, New Formatter.Deserialization.DefaultODataDeserializerProvider)
Dim ser As New Formatter.Serialization.ODataEntityTypeSerializer(_childDefinition, New Formatter.Serialization.DefaultODataSerializerProvider)
Dim dprovider As New Formatter.Deserialization.DefaultODataDeserializerProvider
dprovider.SetEdmTypeDeserializer(_childDefinition, dser)
Dim sprovider As New Formatter.Serialization.DefaultODataSerializerProvider
sprovider.SetEdmTypeSerializer(_childDefinition, ser)
Dim fmt As New Formatter.ODataMediaTypeFormatter(dprovider, sprovider, New List(Of Microsoft.Data.OData.ODataPayloadKind) From {Microsoft.Data.OData.ODataPayloadKind.Entry})
fmt.SupportedEncodings.Add(System.Text.Encoding.UTF8)
fmt.SupportedEncodings.Add(System.Text.Encoding.Unicode)
fmt.SupportedMediaTypes.Add(Headers.MediaTypeHeaderValue.Parse("application/atom+xml;type=entry"))
fmt.SupportedMediaTypes.Add(New Headers.MediaTypeHeaderValue("application/atom+xml"))
I have then tried:
request.content.ReadAsAsync(of User)(new List(of odatamediatypeformatter) from {fmt})
request.content.ReadAsAsync(of User)(request.getConfiguration().formatters)
request.content.ReadAsAsync(of User)(odatamediatypeformatters.create)
All giving the same error, it seems like I'm missing something obvious.
Thanks!
Steve
Just add a parameter of type User to your AddRelation action and you should be good. Web API would automatically invoke the OData formatter to read the User from the request body and bind it to your action parameter.
You can use this helper method to read OData request body,
private static Task<T> ReadODataContentAsAsync<T>(HttpRequestMessage request)
{
var formatters =
ODataMediaTypeFormatters.Create()
.Select(formatter => formatter.GetPerRequestFormatterInstance(typeof(T), request, request.Content.Headers.ContentType));
return request.Content.ReadAsAsync<T>(formatters);
}
like this,
Customer addedCustomer = ReadODataContentAsAsync<Customer>(Request).Result;

Node.js prevent function inspection (toString)

When javascript is run in the browser there is no need to try and hide function code because it is downloaded and viewable in source.
When run on the server the situation changes. There are use cases such as api where you want to provide users with functions to call without allowing them to view the code that which is run.
On our specific case we want to execute user submitted javascript inside node. We are able to sandbox node.js api however we would like to add our own api to this sandbox without users being able to toString the function to view the code which is run.
Does anyone have a pattern or know of a way of preventing users from outputting a functions code?
Update:
Here is a full solution (i believe) based on the accepted answer below. Please note that although this is demonstrated using client side code. You would not use this client side as someone can see the contents of your hidden function by simply reading the downloaded code (although it may provide some basic slow down to inspect the code if you have used a minify).
This is meant for server side use where you want to allow users to run api code within a sandbox env but not allow them to view what the api's do. The sandbox in this code is only to demonstrate the point. It is not an actual sandbox implementation.
// function which hides another function by returning an anonymous
// function which calls the hidden function (ie. places the hidden
// function in a closure to enable access when the wraped function is passed to the sandbox)
function wrapFunc(funcToHide) {
var shownFunc = function() {
funcToHide();
};
return shownFunc;
}
// function whose contents you want to hide
function secretFunc() {
alert('hello');
}
// api object (will be passed to the sandbox to enable access to
// the hidden function)
var apiFunc = wrapFunc(secretFunc);
var api = {};
api.apiFunc = apiFunc;
// sandbox (not an actual sandbox implementation - just for demo)
(function(api) {
console.log(api);
alert(api.apiFunc.toString());
api.apiFunc();
})(api);
If you wrap a callback in a function, you can use another function in that scope which is actually hidden from the callback scope, thus:
function hideCall(funcToHide) {
var hiddenFunc = funcToHide;
var shownFunc = function() {
hiddenFunc();
};
return shownFunc;
}
Then run thusly
var shtumCallBack = hideCall(secretSquirrelFunc);
userCode.tryUnwindingThis(shtumCallBack);
The userCode scope will not be able to access secretSquirrelFunc except to call it, because the scope it would need is that of the hideCall function which is not available.