ASP.Net AutoCompleteExtender VB WebMethod not firing - why? - asp.net

Definitely at my wits end here. This should be simple. In a page to create new user accounts, we have a database with a little of allowable users. To streamline getting the Email address of the new user correct, we want to use an AutoComplete extended textbox.
Now I know that WebMethods are working because I have a cascading-drop-down tied to web methods in another page.
As I'm just starting on this page, the code is simple.
The page itself:
<cc1:ToolkitScriptManager ID="ScriptManager2" runat="server"/>
<p></p> Please enter new user's Email:
<asp:TextBox ID="txtUser" runat="server" />
<cc1:AutoCompleteExtender runat="server" ID="autUser" TargetControlID="txtUser"
ServiceMethod="ScanGALUsers" ServicePath="~/AutoScan.asmx"
MinimumPrefixLength="3" CompletionSetCount="150" /> <p></p>
The .asmx file is simple:
<%# WebService Language="VB" CodeBehind="~/App_Code/VB_Code/AutoScan.vb" Class="AutoScan" %>
The WebMethod:
<System.Web.Script.Services.ScriptService()> _
<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class AutoScan
Inherits System.Web.Services.WebService
<WebMethod()> _
Public Shared Function ScanGALUsers(ByVal strPrefix As String, ByVal intMaxCount As Integer) As String()
Dim arlResults As New ArrayList
Dim intCount As Integer
Dim dt As DataTable
Dim colParameters As New SortedList
SysDA.LogDebug("ScanGALUsers called with parameters: " & strPrefix & " and count of " & intMaxCount.ToString)
... Deleted for brevity ...
If intCount > 0 Then
Dim arrResults(intCount - 1) As String
arrResults = arlResults.ToArray(GetType(System.String))
Return arrResults
Else
Return Nothing
End If
End Function
End Class
I'm not even getting to the LogDebug statement. I've used all the same boilerplate code (Inherits, the 'WebService' tags, etc) that worked in the other WebMethod with the appropriate changes to the Class name but this really has me stumped.
What am I missing that I'm not even making it to the method?

Did you ever resolve this issue? Have you tried removing Shared from your WebService declaration? This has worked for me before (and I don't know why!).

Related

The ConnectionString property has not been initialized for DropDownList

I have the following code:
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Dynamic Reports</title>
<script language="javascript" src="js/DynamicReports.js" type="text/javascript"></script>
</head>
<body onload="doSelect()">
<asp:DropDownList ID="ddlDynReports" runat="server" DataSourceID="sdsDynReports" DataTextField="DynReportName" DataValueField="DynReportID">
</asp:DropDownList>
<asp:SqlDataSource ID="sdsDynReports" runat="server" SelectCommand="select v.object_id as DynReportID, substring(v.name, 11, LEN(v.name)) as DynReportName from sys.views v where v.name like 'DynReport[_]%'">
</asp:SqlDataSource>
</body>
</html>
It throws the following error at runtime:
The ConnectionString property has not been initialized.
My web.config file seems to be okay because I am doing many other sql calls in the .vb code. This is the first time I am doing sql in .aspx code.
I presume my connection that is available in my .vb code needs to be exposed to the .aspx code.
I am open to a solution that would move the select to the .vb code.
EDIT: I figured out that I should add ConnectionString="<%$ ConnectionStrings:constr %>" to the SqlDataSource element, but the problem is that I do not have connection strings in my web.config file. My connection strings are in a file called ApplicationConfig.vb.
So, how can I get the connection string out of ApplicationConfig.vb into the .aspx code?
EDIT: I am doing it this way because it is the sample code I found for populating a dropdown from a select statement. I am a vb.net noob so I am basically surviving by cutting and pasting from the SO. Suggestions for better ways is cheerfully accepted but I get lost if the example code is not complete. Example: Some example code I find on SO looks like what I want to do, but it is a series of snip-its and I don't know where to put those snip-its.
EDIT: Add .vb code:
Partial Class XXX_CommonPages_DynamicReports
Inherits System.Web.UI.Page
Protected Sub dynreport_ServerClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles dynreports_run.ServerClick
Dim ViewObjectId As String = ddlDynReports.SelectedValue
Dim DataOut As String = "some,data,out"
Response.Clear()
Response.AddHeader("Content-Disposition", "attachment; filename=DynReport_" + ViewObjectId + ".csv")
Response.ContentType = "application/octet-stream"
Response.AddHeader("Content-Length", DataOut.Length())
Response.Write(DataOut)
' Response.End ' Causes ThreadAbortException.
End Sub
End Class
EDIT: Here is the .vb code that contains the connection string:
Public Class ApplicationConfig
Public Class AppConfig
Implements IConfigurationSectionHandler
Private Const PRODUCTION_DATAACCESS_CONNECTIONSTRING_DEFAULT As String = "serve ..."
Public Shared ReadOnly Property ConnectionString() As String
Get
If fieldConnectionString Is Nothing Then fieldConnectionString = PRODUCTION_DATAACCESS_CONNECTIONSTRING_DEFAULT
Return fieldConnectionString
End Get
End Property
End Class
End Class

Server Control Error: Unknown server tag with ASP.NET

I am trying to get a custom control working in VB ASP.Net
I've read a few threads but it doesn't seem to help me much.
I have a solution including:
Website project called "SiteCI"
Class Library project called "SiteCI-classes"
The website project has a reference to the library project, and the library DLL are correctly generated inside the bin folder of the website project.
When I create a random class within the website project, I can access to my test control class called MailLink by typing:
SiteCI_classes.Controls.MailLink
It works perfectly, Visual Studio suggests it to me, so the link between the two projects are correctly set.
Please note that I clean/rebuild the project every time to see if it really works or not, so that's not a problem of incorrect DLL build.
In the Web Config file inside system.web -> pages -> controls I have added:
<add assembly="SiteCI-classes" namespace="Controls" tagPrefix="custom" />
But on a ASP.Net page when I add:
<custom:MailLink runat="server" id="test1"></custom:MailLink>
I am getting the Unknown server tag 'custom:MailLink' error.
To check if I did not make a mistake while typing in the web config file I tried to change the SiteCI-classes to SiteCI_classes and I got an error saying that it wasn't able to load the assembly, so I guess that part is OK, and then I tried to change namespace="Controls" in *namespace="SiteCI_classes.Controls"* or namespace="SiteCI-classes.Controls" and it didn't fix the unknown server tag issue.
I don't know what to do... it's supposed to work, isn't it?
Here is the MailLink.vb that is located in a folder called Controls of the Library project. It's a class I picked on a Microsoft page just for testing purpose.
I would be very grateful if anyone could give me a tip on what to check.
Namespace Controls
< _
AspNetHostingPermission(SecurityAction.Demand, _
Level:=AspNetHostingPermissionLevel.Minimal), _
AspNetHostingPermission(SecurityAction.InheritanceDemand, _
Level:=AspNetHostingPermissionLevel.Minimal), _
DefaultProperty("Email"), _
ParseChildren(True, "Text"), _
ToolboxData("<{0}:MailLink runat=""server""> </{0}:MailLink>") _
> _
Public Class MailLink
Inherits WebControl
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(""), _
Description("The e-mail address.") _
> _
Public Overridable Property Email() As String
Get
Dim s As String = CStr(ViewState("Email"))
If s Is Nothing Then s = String.Empty
Return s
End Get
Set(ByVal value As String)
ViewState("Email") = value
End Set
End Property
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(""), _
Description("The text to display on the link."), _
Localizable(True), _
PersistenceMode(PersistenceMode.InnerDefaultProperty) _
> _
Public Overridable Property Text() As String
Get
Dim s As String = CStr(ViewState("Text"))
If s Is Nothing Then s = String.Empty
Return s
End Get
Set(ByVal value As String)
ViewState("Text") = value
End Set
End Property
Protected Overrides ReadOnly Property TagKey() _
As HtmlTextWriterTag
Get
Return HtmlTextWriterTag.A
End Get
End Property
Protected Overrides Sub AddAttributesToRender( _
ByVal writer As HtmlTextWriter)
MyBase.AddAttributesToRender(writer)
writer.AddAttribute(HtmlTextWriterAttribute.Href, _
"mailto:" & Email)
End Sub
Protected Overrides Sub RenderContents( _
ByVal writer As HtmlTextWriter)
If (Text = String.Empty) Then
Text = Email
End If
writer.WriteEncodedText(Text)
End Sub
End Class
End Namespace
I found the problem which seem to have ONLY been caused by the dash ("-") in the name of the Project.
The name of the project is still "SiteCI-Classes" BUT the final code of the WebConfig is different:
<add assembly="SiteCIClasses" namespace="SiteCI2KClasses.Controls" tagPrefix="cc1" />
Note the difference between the two. ASP.Net 3.5 will not recognize a dash in the name of a project and seem to remove it: if you try to set it to SiteCI-Classes it will end up with an error like assembly not found.

Loading usercontrol to string and submitting the form within

What i'm doing is creating a website where the design is done i html files that are then read into the masterpage using System.IO.StreamReader.
and inside the html templates there are keywords like #USER.LOGIN#
that I replace with functions etc.
The issue is that i'm replacing #USER.LOGIN# With a usercontrol where there is a login form.
I have a function that reads the usercontrol into a string and it works.
but since the usercontrol is loaded to string alle the events are not following.
so when I submit the login form nothing nothing happends (the page posts) but cannot get any of the fields from the form...
NOTE:
i'm using url-rewriting so urls are http://www.domain.com/account/login
where account is account.aspx and login is the mode the account is in.
Code for replacing the keyword in the streamreader loop (pr line)
If InStr(line, "#USER.LOGIN#") Then
line = line.Replace("#USER.LOGIN#", vbCrLf & userfunc.GetMyUserControlHtml("uc", "account_login.ascx", "/account/login/") & vbCrLf)
End If
And the functions to read usercontrol
Public Shared Function GetMyUserControlHtml(contextKey As String, controllerfile As String, Optional ByVal formaction As String = "")
Dim myId As Guid = New Guid()
Return userfunc.RenderUserControl("~\Controllers\" & controllerfile, "", myId, formaction)
End Function
Public Shared Function RenderUserControl2(path As String, Optional ByVal formaction As String = "") As String
Using pageHolder As New Page(), _
viewControl As UserControl = DirectCast(pageHolder.LoadControl(path), UserControl), _
output As New StringWriter(), _
tempForm As New HtmlForm()
If formaction <> "" Then
tempForm.Action = formaction
Else
tempForm.Action = HttpContext.Current.Request.RawUrl
End If
tempForm.Controls.Add(viewControl)
pageHolder.Controls.Add(tempForm)
HttpContext.Current.Server.Execute(pageHolder, output, False)
Dim outputToReturn As String = output.ToString()
Return outputToReturn
End Using
End Function
How would you guyz do this?
I need the userlogin to be hardcoded in the usercontrol but still be able to place it anywhere using the template keyword.
This will also be used with other functions (newsletter signup, shoutbox etc.)
what i would suggest is register you control on the web config..
<add tagPrefix="CustomControl" tagName="LogIn" src="~/UserControls/Login.ascx"/>
you can still use "#USER.LOGIN#" but instead of replacing it with a control...
replace it with a something like this
<CustomControl:LogIn id="LogIn" runat="server"/>
this is just a quick write up.. but you could always try if it works
you can save your HTML like this istead of placing an actual "#USER.LOGIN#"
<% =GetLoginControl() %>
and then create a public function in your code behind named GetLoginControl() and return a response.write of the HTML Mark up you need

Subquery returned more than 1 value

I know this topic is all over the place, but I am not doing an INSERT, UPDATE, DELETE. My statement is a plain and simple SELECT statement and so far has worked with 116 different items in my database until I got to one.
I have a search engine and am going through every single product in our database to add information to it. This is all done through the website, but when I search for ProductID 331 and click on it, it goes to the error page that says Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
It doesn't make any sense to me that the website would error with only this one product.
This is the statement I am using. Does anyone know why 1 product would be causing this error?
WebService:
Public Class ProductSearch
Inherits System.Web.Services.WebService
<WebMethod()> _
Public Function GetProducts(ByVal prefixText As String, ByVal count As Integer)
As String()
Dim ProductSql As String = "Select DISTINCT ProductID, ProductName
FROM Product WHERE ProductName
LIKE '%' & #prefixText & '%'
ORDER BY ProductName ASC"
Using sqlConn As New SqlConnection
(System.Configuration.ConfigurationManager.ConnectionStrings
("LocalSqlServer").ConnectionString)
sqlConn.Open()
Dim myCommand As New SqlCommand(ProductSql, sqlConn)
myCommand.Parameters.Add("#prefixText", SqlDbType.VarChar, 50)
.Value = prefixText
Dim myReader As SqlDataReader = myCommand.ExecuteReader()
Dim myTable As New DataTable
myTable.TableName = "ProductSearch"
myTable.Load(myReader)
sqlConn.Close()
Dim items As String() = New String(myTable.Rows.Count - 1) {}
Dim i As Integer = 0
For Each dr As DataRow In myTable.Rows
Dim id As String = dr("ProductID").ToString()
Dim name As String = dr("ProductName").ToString()
Dim item As String = AjaxControlToolkit.AutoCompleteExtender
.CreateAutoCompleteItem(name, id)
items.SetValue(item, i)
i += 1
Next
Return items
End Using
End Function
End Class
The aspx page that calls the webservice:
<%# Page Title="Product Search" Language="VB" MasterPageFile="~/MasterPage.master"
AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="Default" %>
<%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit"
TagPrefix="asp" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
<script type="text/javascript">
function AutoCompleteClientMethod(source, eventArgs) {
var value = eventArgs.get_value();
window.location = ("/Product/Default.aspx?id=" + value)
}
</script>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="body" Runat="Server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="ProductSearch.asmx" />
</Services>
</asp:ScriptManager>
<asp:TextBox ID="Search" runat="server" AutoComplete="off"></asp:TextBox>
<asp:AutoCompleteExtender ID="AutoCompleteExtender1" runat="server"
TargetControlID="Search" ServicePath="~/ProductSearch.asmx"
ServiceMethod="GetProducts" MinimumPrefixLength="1" CompletionSetCount="120"
EnableCaching="true" OnClientItemSelected="AutoCompleteClientMethod">
</asp:AutoCompleteExtender>
</div><!--End of main div -->
</asp:Content>
UPDATE: 11/9/2011 - I have found a couple more records that have this problem. They are ProductID 331-335. I have no idea what is going on here. Could it be that those products don't really exist or that they have some kind of bug?
Here is a list of ProductIDs and their corresponding ProductNames that have this error:
122 'Managed account section of the Web Site'
331 'Elliott Wave Principle Key to Market Behavior'
332 'Targeting Profitable Entry & Exit Points'
333 'Essentials of Trading It's not WHAT You Think, It's HOW You Think'
334 'Exceptional Trading The Mind Game'
335 'Fibonacci Analysis'
I assume this is the sub-select query, DISTINCT doesn't mean one result. You can use TOP 1 to guarantee one result, but it doesn't guarantee it is the one you want.
Select TOP 1 DISTINCT ProductID, ProductName
FROM Product WHERE ProductName
LIKE '%" & prefixText & "%'
ORDER BY ProductName ASC
Besides Rick's answer, I would add that you should never concatenate strings to form SQL statements. Use parametrized queries instead. String concatenation exposes you to SQL Injection attacks. Also, by using parametrized queries you may gain performance if the query plans can be reused.
See this other StackOverflow post for a good discussion regarding parametrized queries on VB.NET.
I figured out what the problem is. For some reason, these problematic products have more than one value assigned to them in data fields that SHOULD have only one item. The database has been changed recently so that doesn't happen, but I guess these 5 products were already messed up and have now been found out.
Thanks for all the help guys! I wish I would've thought to check further into the database sooner. (There are about 15 tables, so it's usually what I think of to do last)

call a vb.net subrouting from a javascript function?

hi folks i have a subroutine called CheckDate() in the code behind.
How would I call that subroutine from a javascript function?
Cheers,
-Jonesy
You can't call it directly as function call.
because Javascript is a scripting langauge aimed for web browsers.
you may use AJAX or full page post sending the parameters to allow you to execute the subroutine.
Read more about Ajax it is the better way to go.
To expand on what Kronass said there I've found this article to be useful in the past for doing what you want http://encosia.com/2008/05/29/using-jquery-to-directly-call-aspnet-ajax-page-methods/. Encosia also has a heap of other blog plots on this if you do a bit of searching
What you're looking to use is normally called a WebMethod, ScriptMethod or Page Method depending on which framework you're using
One way to do this is by using the ICallbackEventHandler interface. I saw you had a question regarding the AjaxControToolkit CalendarExtender the other day so I'm guessing this question is in relation to that and how you do some validation in a server-side method. ICallbackEventHandler is AJAX, but you can write your validation as a normal method, not a PageMethod/WebMethod. It's slightly more fiddly on the Javascript side, but not by much.
Let's start with our basic textbox and calendar extender:
<form id="form1" runat="server">
<asp:ScriptManager runat="server" ID="ScriptManager" />
<div>
<asp:TextBox runat="server" ID="DateTextBox" />
<ajaxtoolkit:CalendarExtender runat="server" ID="CalendarExtender" TargetControlID="DateTextBox"
PopupButtonID="SelectorButton" OnClientDateSelectionChanged="checkDate" Format="dd MMM yyyy" />
<asp:ImageButton runat="server" ID="SelectorButton" ImageUrl="Path to a pretty graphic" />
<br />
<asp:Label runat="server" ID="ValidDateLabel" />
</div>
</form>
I've added the OnDateSelectionChanged attribute of the extender as this will kick off the process of calling the server-side method; we'll come back to what goes in there shortly.
In the class declaration in your code-behind, you need to say that you are implementing the interface:
Partial Public Class _Default
Inherits System.Web.UI.Page
Implements ICallbackEventHandler
To implement the interface we then need to add two more methods to handle the two methods in the interface, RaiseCallbackEvent and GetCallbackResult. We also need a property for a bit of temporary storage of the date we are trying to validate.
Private mCallbackDate As Date
Private Property CallbackDate() As Date
Get
Return mCallbackDate
End Get
Set(ByVal value As Date)
mCallbackDate = value
End Set
End Property
Public Sub RaiseCallbackEvent(ByVal eventArgument As String) Implements ICallbackEventHandler.RaiseCallbackEvent
'eventArgument will contain the date the user selected from the extender
Dim testDate As Date
If eventArgument = String.Empty Then
Else
If Date.TryParse(eventArgument, testDate) Then
'If we have a legal date selected then store it
Me.CallbackDate = testDate
End If
End If
End Sub
Public Function GetCallbackResult() As String Implements ICallbackEventHandler.GetCallbackResult
Dim result As String = String.Empty
'Get the date that we stored in memory and pass it to our CheckDate function
'We'll pass back to the Javascript in the page the string 'true' if the date is
'valid under our business rules and 'false' if it isn't
If checkDate(Me.CallbackDate) Then
Return "true"
Else
Return "false"
End If
End Function
Public Function checkDate(ByVal dateToCheck As Date) As Boolean
'If the date is in the future then return True, otherwise False
If dateToCheck > Date.Today Then
Return True
Else
Return False
End If
End Function
There's one more bit of server-side we need to add, in Page_Load, which does the hooking up of the Javascript and server-side code. The ClientScriptManager's GetCallbackEventReference function will inject a bit of script into our page that takes care of the communication between browser and server. Then we just need to register a script block that calls the injected script - we'll call this function checkDateOnServer.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim callbackScript As String
callbackScript = "function checkDateOnServer(arg){" & _
Page.ClientScript.GetCallbackEventReference(Me, "arg", "receiveDateValidation", "") & _
"}"
ClientScript.RegisterClientScriptBlock(Me.GetType, "callback", callbackScript, True)
End Sub
Back to the client-side bits. We need to write a Javascript checkDate function that'll pass the user's selected date into the callback.
function checkDate()
{
// Get the date the user selected
var selectedDate = document.getElementById('DateTextBox').value;
// This will start the callback sequence
checkDateOnServer(selectedDate);
}
The last bit we need to do is receive the value coming back from the server, which we said in Page_Load would be called receiveDateValidation.
function receiveDateValidation(arg, context)
{
var ValidDateLabel = document.getElementById('SelectedDateLabel');
// We get a string value back from the server which is 'true' or 'false'
if (arg == 'true')
{
ValidDateLabel.innerText = 'Your date IS valid';
}
else
{
ValidDateLabel.innerText = 'Your date IS NOT valid';
}
}

Resources