C# Click HTML Button from Webclient - c#

I'm working on a Windows Forms Application. I want the webclient to post the values from the NameValueCollection and then hit the submit button. But now it only adds the values to the html but never submits them. How can I simulate this buttonclick?
private void button2_Click(object sender, EventArgs e)
{
var requestData = new NameValueCollection
{
{"prodids", "somevalue" },
{"customerid", "somevalue" },
{"submit_button", "submit" }
};
byte[] request = client.UploadValues("myurl", "POST", requestData);
string result = Encoding.UTF8.GetString(request);

You need to get the <form> element that contains you button, and then get its action attribute. That's the URL that your client should make a request to. You might need to get also the action attribute to find out whether to make GET or POST request.
The thing is, the button itself is not important: in the web browser, if it has action "submit" it just triggers the containing form to serialize contents and send them to the action url using `method.
When you use a client to interact with a webpage, you cannot be thinking of it like of a web browser, more like downloading a page and opening it with a text editor. Nothing's clickable, there's no JS, there's nothing even rendered - it's just the raw content sent from the server.
EDIT:
So, this is done purely with JavaScript, which is all kinds of wrong. Anyhow, your method is POST and your action is /View/DashboardProxy.php?location=Dashboard/RequestServlet&postdata=1, so your call will be:
byte[] request = client.UploadValues("/View/DashboardProxy.php?location=Dashboard/RequestServlet&postdata=1", "POST", requestData);
Note, that the response will not be a full page, but possibly nothing or some text to put in post_result_textarea.
Oh, and also note that there are more than 3 values passed in that POST request - values from: server_id, prodids, shopid, customerid and specialbids. Possibly the server requires all of those fields to be filled.

You could use AJAX with WebMethod. (this example uses jQuery for the ajax requests but you could aswell do this with plan vanilla javascript)
$.post({
type: "POST",
url: /Default.aspx/methodX,
data: data,
dataType: dataType
}).done(function(data){
if (data === true) {
console.log('everything worked out fine.')
}
});
and edit your .cs file with the following.
[WebMethod]
public bool methodX(string data) {
var requestData = new NameValueCollection
{
{"prodids", "somevalue" },
{"customerid", "somevalue" },
{"submit_button", "submit" }
};
byte[] request = client.UploadValues("myurl", "POST", data);
string result = Encoding.UTF8.GetString(request);
return true;
}
or similar.. hope you get an idea from this.
Read more
http://api.jquery.com/jquery.post
https://msdn.microsoft.com/en-us/library/4ef803zd(v=vs.90).aspx

Related

Parse JSON from C# to AngularJS

I have an array of file names:
[HttpPost]
public JsonResult GetJSONFilesList()
{
string[] filesArray = Directory.GetFiles("/UploadedFiles/");
for (int i = 0; i < filesArray.Length; i++)
{
filesArray[i] = Path.GetFileName(filesArray[i]);
}
return Json(filesArray);
}
I need this in AngularJS as a list of objects so I can ng-repeat it out and apply filters. I'm unable to figure out how to get the JSON from the MVC controller to AngularJS.
I've tried the following to make it visible to the view for angular to grab, but I don't know how to make the ng-init see the function to return the list. It erros on "SerializeObject(GetJSONFilesList())" saying it doesn't exist in current context.
<div ng-controller="MyController" data-ng-init="init(#Newtonsoft.Json.JsonConvert.SerializeObject(GetJSONFilesList()),
#Newtonsoft.Json.JsonConvert.SerializeObject(Model.Done))" ng-cloak>
</div>
EDIT:
I've tried using http.get.
Test one:
alert('page load');
$scope.hello = 'hello';
$http.get('http://rest-service.guides.spring.io/greeting').
then(function (response) {
$scope.greeting = response.data;
alert($scope.greeting);
});
alert($scope.hello);
The alert in the http.get never fires, the other alerts do however.
Test two:
$http({
url: '/Home/testHello',
method: 'GET'
}).success(function (data, status, headers, config) {
$scope.hello = data;
alert('hi');
});
[HttpPost]
public string testHello()
{
return "hello world";
}
This causes the angular to break and nothing in the .js works.
Test three
alert('page load');
$scope.hello = 'hello';
$scope.GetJSONFilesList = function () {
$http.get('/Home/testHello')
.success(function (result) {
$scope.availableFiles = result;
alert('success');
})
.error(function (data) {
console.log(data);
alert('error');
});
alert('hi');
};
alert($scope.hello);
[HttpPost]
public string testHello()
{
return "hello world";
}
Alerts nothing from within it, other alerts work.
Fixed:
After some googling, I've found that using .success and .error are deprecated and that .then should be used. So by using .then this resulted in the C# being hit via debug.
Then after using console.log on the returned value found that to have anything be returned I needed to return the value from C# using "return Json(myValue, JsonRequestBehavior.AllowGet); "
And by viewing the object in the console in Chrome by using console.log, I could see my values were in the data part of the returned object.
It was stored in data as an array (as I was passing an array).
I could then get the data out of there by assigning the returned value.data to a scope and could call that in the view {{result[1]}} etc.
return Json(filesArray, JsonRequestBehavior.AllowGet);
$scope.fileList;
$http.get("/Home/GetFileList").then(function (result) {
console.log(result)
$scope.fileList = result.data;
})
Imagine that you divide your front end in three layers (MVC or MVVM) whatever you want.
When you need info from server, the best practice is to separate the logic that makes the request and the logic that manipulates the data.
More info about how to make the request you can find it reading about REST APIS in Consuming a RESTful Web Service with AngularJS.
Normally one of the layers requires the use of services and you can have your controllers and your services (the place where you get the raw data from the server and you make the request. For that you need to use the $http service from angularjs.
$http: The $http service is a core AngularJS service that facilitates communication with the remote HTTP servers via the browser's XMLHttpRequest object or via JSONP.
So basically it shows you how to make get, post and put requests. One example from the documentation is :
// Simple GET request example:
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Pay attention to the url because there is the place where you let your request knwow which method is going to be hit on the server to take the action. If your request is succesful, then you can use the parameter called response. From there, you can do whatever you want. If you decide to make that request part from your controller, you can assign it directly to a variable on your scope. Pay attention if you need to serialize the data. Something like
$scope.myResponseName = response.name ;
The first documentation link from above shows this example which does exactly what I tell you.
angular.module('demo', [])
.controller('Hello', function($scope, $http) {
$http.get('http://rest-service.guides.spring.io/greeting').
then(function(response) {
$scope.greeting = response.data;
});
});
After all the mentioned above, pay attention to what you want to display. Are you going to display the elements of an object array? The use on your HTML the ng-repeat directive. Are you going to display just a variable (No array nor object) then you use need to use an angular expression {{ }}
In summary:
By making an HTTP request, hit the correct method on server.
Make sure you are sending the JSON correctly and that the data is correct.
Retrieve the data on your response.
Assign the data to a variable on your scope and serialize the data if needed.
Display the data correctly depending if it is within an array, if it´s an object or if its just a variable.
I hope the explanation makes sense and check the documentation if you need more info.
You can build your viewmodel so that it contains the data you'd like to serialize and then pass it to angularJS in your view as follows:
<div ng-controller="MyController" data-ng-init="init(#JsonConvert.SerializeObject(myArrayData),
#Newtonsoft.Json.JsonConvert.SerializeObject(Model.Done))" ng-cloak>
and then in your angular controller have a function to receive the data as follows:
$scope.init = function (myArrayData) {
//do something with data
};
The above assumes you're trying to pass data from mvc to angularjs on page load. If you're trying to hit a controller and get data back to angularjs upon some event such as a button click, then you can write an angularjs function similar to the following (this will be an asynchronous request):
app.controller('MyController', function ($scope, $http, $window) {
$scope.ButtonClick = function () {
var post = $http({
method: "POST",
url: "/SomeController/SomeAjaxMethod",
dataType: 'json',
data: { path: $scope.Path},
headers: { "Content-Type": "application/json" }
});
post.success(function (data, status) {
//do something with your data
});
post.error(function (data, status) {
$window.alert(data.Message);
});
}
}
and your controller action would look something like:
[HttpPost]
public JsonResult SomeAjaxMethod(string path)
{
string[] filesArray = Directory.GetFiles(path);
for (int i = 0; i < filesArray.Length; i++)
{
filesArray[i] = Path.GetFileName(filesArray[i]);
}
return Json(filesArray);
}
other answers say to use .success in the angular function, .success and .error are deprecated, instead .then should be used.
Working result:
MVC:
public JsonResult GetFileList()
{
//form array here
return Json(myArray, JsonRequestBehavior.AllowGet);
}
The function needs to be of type JsonResult, and the returned value of Json using JsonRequestBehavior.AllowGet.
AngularJS:
$scope.fileList;
$http.get("/Home/GetFileList").then(function (result) {
console.log(result)
$scope.fileList = result.data;
})
This is in my AJS controller, using .then instead of .success. If you use console.log the result returned from the mvc controller and view it in the browser inspect you'll see the object with lots of other info and the values you want are in the .data section of the object.
So to access the values you need to do result.data. In my case this gives me and array. I assign this to a scope. Then in my view I can access the values by doing {{fileList[1]}} etc. This can also be used in ng-repeat e.g:
<div ng-repeat="file in fileList">
{{fileList[$index]}}
</div>
Each value in the array in the repeat can be accessed using $index which is the number of the repeat starting at 0.

Ajax call gets cached, despite the appropriate parameter

I'm currently writing a MVC C# application. Everything works just fine. I have a bit of functionality, where I fill up a Bootstrap modal box using an Ajax call, but the new page gets cached, despite my efforts to prevent that.
On my main page I have the following actionhandler to fill up the modal box:
function setExtraPermsOrAtts(appID){
$.ajax({
cache:false,
url: "/Group/_modifyAppPermissionsOfGroup?appID=" + appID
}).done(function (result) {
$("#addApplicationBody").html(result);
$('#modal-add-application').modal('show');
});
}
This gets caught by the following method:
public ActionResult _modifyAppPermissionsOfGroup(int? appID = 0)
{
if (appID != 0)
{
ViewBag.selectedAppID = appID;
Session["selectedGroupAppID"] = appID;
ViewBag.modifyPermsLater = true;
}
Group group = (Group)Session["currentGroup"];
return View(group);
}
Another thing that might be relevant is the point where it 'goes wrong'. The resulting View in the Modalbox, has a few radio buttons, depending on the content of the database. There I do a razor statement to get the DB value:
bool valueOfRadButtons = BusinessLogic.Domain.GroupIS.getExistingGroupPermission(
Model.LoginGroupID, myItem.ApplicationPermissionID).LoginPermissionState;
Does anyone know where I'm going wrong? Is it the Ajax call? The ActionResult method in the Controller? Or the inline razor statement? I know the data gets saved properly, cause I see so in the DB
You can specify that the response shouldn't be cached like this:
Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
Response.Cache.SetValidUntilExpires(false);
Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetNoStore();
It can be more easy if you make your own attribute and decorate the action with it as shown here.

Resolve Controller Path in Javascript File

I'm using a Kendo grid to display results from a webservice. The webservice is accessed in a controller and then we point the Kendo grid dataSource to the controller like so:
JavaScript
var servicePath = "/Home/Search";
var postData = { "searchTerm" : searchTerm, "targetDB" : targetDB }
var grid = $("#grid1").kendoGrid({
pageable: {
pageSize: 10
},
dataSource: {
error: function (e) {
if (e.errors !== false) {
$("#errorContainer").html(e.errors);
}
},
transport: {
read: {
url: servicePath,
dataType: "json",
data: postData,
type: "POST"
}
},
},
dataBound: function (e) {
//Do Stuff
}
});
Controller
[HttpPost]
public ActionResult Search(string searchTerm, string targetDB)
{
//Do Search and Return JSON
}
Problem
This works wonderfully when my URL is http://localhost/Home/Index but fails whenever it's something else, such as http://localhost/ (default when project is run from root). I've experienced the same problems using a jQuery .ajax call as the kendo grid service call.
Question
So my question is, how can I put in the correct service URL for the Kendo Grid (or in general when pointing to a controller) and know it will work in all path variations?
I've tried using variations of location.host to get the full URL regardless then append the controller and method, but the Kendo service call fails with no error.
I imagine I should be able to parse the url and use what I need, but I've found that when I am at the root of the webpage I can't figure out what to put to make an ajax call work. I've tried using the controller/method and the entire url? I've also tried various techniques described below.
What am I missing? Is there a convention or technique I could use instead?
Edit
I also tried putting a hidden field on the page with a value of the controller URL:
<input type="hidden" value="#Url.Action("Search", "Home"); " id="serviceURL" />
And then using that value in the JS:
var servicePath = $("#serviceURL").val();
But I found that the value of #Url.Action() (Value : Home/Search) is the same whether your url is http://localhost/ or http:localhost/Home/Index, so no luck. This still does not work when you're on the root page where the url looks something like "localhost/".
Thanks!

How to call an MVC Action using only JavaScript?

I have this Kendo UI dropdownlist with a select event that is handled by a JavaScript function.
I need to call an action result from a controller that runs a LINQ query to populate a Kendo UI grid on my page. My problem is the only way I can find to handle this even is with JavaScript and I have been unable to figure out how to call my action result from my controller from the JavaScript event function.
This is what the DropDownList looks like...
#(Html.Kendo().DropDownList()
.Name("Options")
.DataTextField("Text")
.DataValueField("Value")
.BindTo(new List<SelectListItem>() {
new SelectListItem() {
Text = "Policies Not Archived",
Value = "1"
},
new SelectListItem() {
Text = "View All Policies",
Value = "2"
},
new SelectListItem() {
Text = "Filter Policies",
Value = "3"
}
})
.Events(e =>
{
e.Select("select");
})
)
and my JavaScript event handler that needs to call the action result
function select(e) {
}
and depending on the selection an ActionResult like this,
public ActionResult ViewAllPolicies()
{
//mycode
}
see this post
var url = '#Url.Action("ViewAllPolicies","YourController")';
$.ajax({ url: url, success: DataRetrieved, type: 'POST', dataType: 'json' });
in controller
public ActionResult ViewAllPolicies()
{
//Should return json format
}
url – this is the URL where request is sent. In my case there is
controller called contacts and it has action calles
ListPartiesByNameStart(). This action method takes parameter
nameStart (first letter of person or company). success – this is the
JavaScript function that handles retrieved data. You can write there
also anonymous function but I suggest you to use functions with names
because otherwise your code may get messy when functions grow. type –
this is the type of request. It is either GET or POST. I suggest you
to use POST because GET requests in JSON format are forbidden by
ASP.NET MVC by default (I will show you later how to turn on GET
requests to JSON returning actions). dataType – this is the data
format that is expected to be returned by server. If you don’t assign
it to value then returned result is handled as string. If you set it
to json then jQuery constructs you JavaScript object tree that
corresponds to JSON retrieved from server.
Instead of returning json, you can also return a PartialView and in the .done function grab an element and replace it with the results from the partial view. PartialView actions basically return a fragment of HTML, and so you can just stuff that anywhere you want on the page:
$.ajax({
url: urlToPartialViewAction,
type: 'POST',
dataType: 'JSON',
data: '123'
})
.done(function (result) {
$('#someDivPlaceholder').replaceWith(result);
});
You could have something like a link or grey div and wire up to it's click event and then call this, the link might say "View Receipt" and when you click it you call an action that returns a partial view with the receipt, and so when they click it the div/link is replaced with the result. Kind of like the "View More Comments" links you see on social sites.
Note that you can't have a partial view by itself, it must be called through an action
public PartialViewResult _GetReceipt(string id)
{
ReceiptViewModel vm = //query for receipt data
return PartialView(vm);//render partial view and return html fragment
}
Once the select function executes, you need to make an AJAX call back to your Controller. You can use jQuery.ajax() (a wrapper for the most common AJAX operations) in the select function,
function select(e) {
var url = '#Url.Action("ViewAllPolicies", "PolicyController")';
var selectedPolicy = $('#Options').val(); // The option selected
$.ajax({
url: url,
type: 'POST',
dataType: 'JSON',
data: selectedPolicy
})
.done(function (data) {
// Display the data back from you Controller
});
}
You can look at the Kendo site for more info on how the DropDownList works.

Getting wrong Url.PathAndQuery

I have an action link:
#Html.ActionLink("Shopping cart", "Index", "Cart", new { returnUrl = Request.Url.PathAndQuery }, null)
and code that adds items to cart:
<script type="text/javascript">
$(document).ready(function () {
$("#addToCart_#(Model.ProductID)").click(function () {
var quantity = $("#Quantity_#(Model.ProductID)").val();
var productId = "#Model.ProductID";
var dataToBeSent = { 'quantity': quantity, 'productId': productId};
$.ajax({
type: "POST",
url: '/Cart/AddToCart/',
data: dataToBeSent,
success: function (result) {
$('#cartholder').html(result);
}
});
});
});
</script>
When I'm trying to follow action link after adding item to cart, Request.Url.PathAndQuery has value /Cart/AddToCart/.
How can I get current url?
You need to use:
Request.RawUrl
This will get the URL you see in the browser. When using Url writing as with MVC the Request.Url will be the rewritten path.
Looks to me like you are setting your URL to /Cart/AddToCart/. It's right there in your AJAX request: url: '/Cart/AddToCart/'. That's it -- that's your URL (not counting the scheme and host).
You're specifying type: "POST", so your payload (your data: dataToBeSent) isn't sent as part of the URL. The data only gets sent in the URL when you use GET. When you use POST, it's in the request body, not the URL.
(And don't just change it to a GET. It would seem to work for now, but would give you headaches later. GET requests can be cached by proxy servers -- not appropriate for requests that modify state, like adding things to a shopping cart.)
So in answer to the question you asked, Request.Url.PathAndQuery is how you get the URL. It's just that the URL is not what you want. You want to get your POST data, however that's normally done in ASP.NET MVC.
System.Web.HttpContext.Current.Request.Url

Categories