Get DataTable from aspx using VB 2010 - asp.net

I am creating a VB 2010 desktop application. I use the lines below to get a string response from an aspx page that I use to collect online data for the application.
Dim response As Byte() = myWebClient.UploadValues(myWeb & "/Default.aspx", "POST", nmv)
dim str as string = Replace(System.Text.Encoding.ASCII.GetString(response), "<(.|\n)*?>", "")
System.Text.Encoding.ASCII.GetString(response)
'nmv' is a defined NameValueCollection variable
Now I need to get this data back from the aspx page as either as nmv or a datatable. Is that possible? How could I go about doing it? I am thinking the key is in the System.'Array'... or something but I can't figure it out and I don't get any search results on the web.
Getting the data back as a string array is good for me, getting it nmv is even better; but getting it back as a DataTable would be perfect! I am able to deal with the aspx page giving back the data in any format, I just need the vb app to know how to collect it.
Thank you

You can change the content type of the aspx from text to image or pdf etc. but not a complex datatype.
I would use a web service or wcf service instead. You can just declare a method of DataTable type and you're done.
http://msdn.microsoft.com/en-us/library/ms972326.aspx

Maybe easiest way would be to use *.ashx Http Handler (generic handler) and save DataTable to XML, something like this :
Server:
public class Handler1 : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
/// if needed request data is in context.Request
DataTable tbl = GetDataTable();
/// table must have name, if not WriteXml will fail
tbl.TableName = "TableName";
tbl.WriteXml(context.Response.OutputStream);
}
public bool IsReusable
{
get
{
return false;
}
}
Then on client you should use ReadXml DataTable method to populate DataTable on client.

Related

How do QueryString parameters get bound to Action method parameters?

I have a webforms project, and am attempting to run some code that allows me to make a call to an MVC route and then render the result within the body of the web forms page.
There are a couple of HttpResponse/Request/Context wrappers which I use to execute a call to an MVC route, e.g.:
private static string RenderInternal(string path)
{
var responseWriter = new StringWriter();
var mvcResponse = new MvcPlayerHttpResponseWrapper(responseWriter, PageRenderer.CurrentPageId);
var mvcRequest = new MvcPlayerHttpRequestWrapper(Request, path);
var mvcContext = new MvcPlayerHttpContextWrapper(Context, mvcResponse, mvcRequest);
lock (HttpContext.Current)
{
new MvcHttpHandlerWrapper().PublicProcessRequest(mvcContext);
}
...
The code works fine for executing simple MVC routes, for e.g. "/Home/Index". But I can't specify any query string parameters (e.g. "/Home/Index?foo=bar") as they simply get ignored. I have tried to set the QueryString directly within the RequestWrapper instance, like so:
public class MvcPlayerHttpRequestWrapper : HttpRequestWrapper
{
private readonly string _path;
private readonly NameValueCollection query = new NameValueCollection();
public MvcPlayerHttpRequestWrapper(HttpRequest httpRequest, string path)
: base(httpRequest)
{
var parts = path.Split('?');
if (parts.Length > 1)
{
query = ExtractQueryString(parts[1]);
}
_path = parts[0];
}
public override string Path
{
get
{
return _path;
}
}
public override NameValueCollection QueryString
{
get
{
return query;
}
}
...
When debugging I can see the correct values are in the "request.QueryString", but the values never get bound to the method parameter.
Does anyone know how QueryString values are used and bound from an http request to an MVC controller action?
It seems like the handling of the QueryString value is more complex than I anticipated. I have a limited knowledge of the internals of the MVC Request pipeline.
I have been trying to research the internals myself and will continue to do so. If I find anything I will update this post appropriately.
I have also created a very simple web forms project containing only the code needed to produce this problem and have shared it via dropbox: https://www.dropbox.com/s/vi6erzw24813zq1/StackMvcGetQuestion.zip
The project simply contains one Default.aspx page, a Controller, and the MvcWrapper class used to render out the result of an MVC path. If you look at the Default.aspx.cs you will see a route path containing a querystring parameter is passed in, but it never binds against the parameter on the action.
As a quick reference, here are some extracts from that web project.
The controller:
public class HomeController : Controller
{
public ActionResult Index(string foo)
{
return Content(string.Format("<p>foo = {0}</p>", foo));
}
}
The Default.aspx page:
protected void Page_Load(object sender, EventArgs e)
{
string path = "/Home/Index?foo=baz";
divMvcOutput.InnerHtml = MvcWrapper.MvcPlayerFunctions.Render(path);
}
I have been struggling with this for quite a while now, so would appreciate any advice in any form. :)
MVC framework will try to fill the values of the parameters of the action method from the query string (and other available data such as posted form fields, etc.), that part you got right. The part you missed is that it does so by matching the name of the parameter with the value names passed in. So if you have a method MyMethod in Controller MyController with the signature:
public ActionResult MyMethod(string Path)
{
//Some code goes here
}
The query string (or one of the other sources of variables) must contain a variable named "Path" for the framework to be able to detect it. The query string should be /MyController/MyMethod?Path=Baz
Ok. This was a long debugging session :) and this will be a long response, so bear with me :)
First how MVC works. When you call an action method with input parameters, the framework will call a class called "DefaultModelBinder" that will try and provide a value for each basic type (int, long, etc.) and instance of complex types (objects). This model binder will depend on something called the ValueProvider collection to look for variable names in query string, submitted forms, etc. One of the ValueProviders that interests us the most is the QueryStringValueProvider. As you can guess, it gets the variables defined in the query string. Deep inside the framework, this class calls HttpContext.Current to retrieve the values of the query string instead of relying on the ones being passed to it. In your setup this is causing it to see the original request with localhost:xxxx/Default.aspx as the underlying request causing it to see an empty query string. In fact inside the Action method (Bar in your case) you can get the value this.QueryString["variable"] and it will have the right value.
I modified the Player.cs file to use a web client to make a call to an MVC application running in a separate copy of VS and it worked perfectly. So I suggest you run your mvc application separately and call into it and it should work fine.

asp.net return data in Page_Load

If a query string param exists in my page request I want to query the database on the server in the Page_Load and then return the result to the client. I can do the query string param check and query the DB but how do I return the data to the page and on the javascript side how do I access that data?
Ideally I would return JSON of an object structure and it would be returning an array of them.
Yes, returning JSON would be the best option. I'm not sure how you query your database (Do you use LINQ or ADO.NET DataTables, etc)
If you don't have custom object of type you want to send, I recommend you create one. Then you should get an array of them.
Example:
public class Person {
string Name { get; set; }
int Age { get; set; }
}
Person[] pArr = new Person[5];
Then you can use a third party library like this to create an string representaion of that array in JSON.
string json = JsonConvert.SerializeObject(product);
Then you write that json string to the Response object so its sent down to the client, by overriding the Render method of the page.
// Don't expect this code to work as it is, but take this as a guidance
Response.Clear();
Response.Write(json);
Response.Close();
on the client side use jQuery library send a request to page, and process the JSON response for you.
$.getJSON('url', function(data) {
//process data
});
Here is my suggestion if you don't want to use an AJAX request for this:
Use the objects as you would normally do in the page_load, and convert it to a JSON string as explained above.
Then use ClientScriptManager to create an JavaScript variable on the client side when it loaded.
ClientScript.RegisterClientScriptBlock(typeof(Page), "unique_key", "var myObjectList = " + json, true);
After this when the page loads you will have an variable named "myObjectList" with the list of objects without having to make a different AJAX call.
You can directly refer that variable in your javascript and do necessary processing.
Hope this helps.

Windows Azure access POST data

Ok, so I can't seem to find decent Windows Azure examples. I have a simple hello world application that's based on this tutorial. I want to have custom output instead of JSON or XML. So I created my interface like:
[ServiceContract]
public interface IService
{
[OperationContract]
[WebInvoke(UriTemplate = "session/create", Method = "POST")]
string createSession();
}
public class MyService : IService
{
public string createSession()
{
// get access to POST data here: user, pass
string sessionid = Session.Create(user, pass);
return "sessionid=" + sessionid;
}
}
For the life of me, I can't seem to figure out how to access the POST data. Please help. Thanks!
If you have an HttpContext there may be a Request object that would have the form data. I'm basing part of this off the ASP.Net tag on this question, so if that is incorrect then there may be the need to handle this another way but it looks a lot like a web service to my mind.
EDIT: HttpRequest is the class that has the Form property that should be where the POST data is stored if this is an HTTP request. This is part of System.Web so it should be ready to be used pretty easily, as I recall.
Sample code showing the Request.Form property:
int loop1;
NameValueCollection coll;
//Load Form variables into NameValueCollection variable.
coll=Request.Form;
// Get names of all forms into a string array.
String[] arr1 = coll.AllKeys;
for (loop1 = 0; loop1 < arr1.Length; loop1++)
{
Response.Write("Form: " + arr1[loop1] + "<br>");
}
This presumed there was an HttpRequest instance around.
WCF Simplified Part 4: Comparing the Request/Reply and One-Way Patterns passes in a parameter so that your "createSession" method would have to take in those strings it would appear. I'm used to the ASP.Net world where there are some built-in objects like Request, Response, Server, Application and Session.
Yes, if you did try changing the method signature as there are ways to pass in parameters in that last example I linked though I don't know if that would work in your case or not.

ASP.NET Web Service returns IndexOutOfRangeException with arguments

I have the following web service:
[ScriptService]
public class Handler : WebService {
[WebMethod]
public void method1() {
string json = "{ \"success\": true }";
System.Web.HttpContext.Current.Response.Write(json);
}
[WebMethod]
public object method2(Dictionary<string, object> d) {
Dictionary<string, object> response = new Dictionary<string, object>();
response.Add("success", true);
return response;
}
}
The first method accepts a traditional html form post and response writes a JSON string to the page. The second method accepts a JSON value posted via AJAX and returns a serialized object.
Both these methods work fine on their own but when put together in the same web service I get this error when calling method1:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
When I remove the arguments from method2 they work.
Can anyone suggest why this is happening?
Edit:
The problem spans from the argument type of method2. If I change it to a string or simple data type it works fine. As Joel suggests it's probably because Dictionaries can't be serialized. This doesn't seem to affect my requests sent by ajax and only breaks direct form posts to this handler. Therefore my workaround is to put the form post handlers in a separate file by themselves. Not ideal but works for my application.
Dictionaries are not serializable. Hiding it behind an object doesn't do anything for you. You must first convert your dictionary to an array or some other serializable object before sending it out.
Why isn't there an XML-serializable dictionary in .NET?
http://weblogs.asp.net/pwelter34/archive/2006/05/03/444961.aspx
http://www.tanguay.info/web/index.php?pg=codeExamples&id=333

Better way to get Page Name

I'm using this to get the current page name..so this returns for example MyPage.aspx
public string GetCurrentPageName()
{
string urlPath = Request.Url.AbsolutePath;
FileInfo fileInfo = new FileInfo(urlPath);
string pageName = fileInfo.Name;
return pageName;
}
There has to be an easier way? Meaning there's got to be an existing method or property in the .NET framework one would think.
The way I interpret the question, what you're looking for is an efficient way of retrieving the name of the currently executing aspx page, i.e. System.Web.UI.Page.
If that is true you shouldn't have to deal with any FileInfo objects or hit the filesystem. Simply use the AppRelativeVirtualPath property on the page object:
using System;
using System.IO;
using System.Web.UI;
namespace WebApplication1
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string pageName = Path.GetFileNameWithoutExtension(Page.AppRelativeVirtualPath);
}
}
}
If you want to get the fully-qualified (or "rooted") path of your currently executing page you can use Server.MapPath like this:
string path = Server.MapPath(Page.AppRelativeVirtualPath);
Using AppRelativeVirtualPath has the benefit of working even when you're using URL rewriting and, since it doesn't use Request.Url (which is provided by your users), you don't have to worry about potentially malicious data.
Would HttpContext.Current.CurrentHandler be what you're looking for?
Since you're more interested in the physical file name vs the page object something along the lines of
var page = (Page) HttpContext.Current.CurrentHandler;
string url = page.AppRelativeVirtualPath;
This along with the information from #Markus Olsson can give you access to the page in any point during its execution even if you're outside of page class.
I use Request.Url.Segments.Last() , which I think is elegant enough.
just for interest I did little search with intellisence. did not found any property. still same logic in other way round.
string currentPageName = System.IO.Path.GetFileName(Request.Url.AbsolutePath);
As was pointed out in one of the answers to this earlier question of yours, I'd go for an option that didn't need me to create a FileInfo object.
There isn't always a direct mapping between a requested page and a file system object, especially when routing/url rewriting etc comes in to play.
Dim MyPage As String = Path.GetFileName(Page.AppRelativeVirtualPath.ToString).ToString
This one works for me
Not much better, but you could try this extension method:
public static string GetPageName(this Page myPage)
{
FileInfo fi =new FileInfo(myPage.MapPath(myPage.AppRelativeVirtualPath));
return fi.Name;
}
and just call it in your page's "OnInit" or whatever method as:
string pageName = this.GetPageName();
Marc
System.IO.Path.GetFileName(Request.PhysicalPath)

Resources