I'm not sure of the best way to accomplish my goal. Looking for insight. I'm familiar with WebAPI services consumed through WPF and Silverlight but this is my first run at ASP and MVC.
I am building a site to verify contents of a shipment against an electronic manifest (EDI 856). I have a page that displays the shipping data and I need the users to scan each item barcode in the container. I would then like to pass that barcode to a service, verify the item belongs in that shipment and then update the page to show as much.
My plan was to have a single text box into which the user could scan/type the barcode and then submit that data to a WebAPI service which would verify the information and then probably use SignalR to send a message back to the page and update a grid with the item data.
If this is a decent way to go, I'm just not quite sure how to use ajax to call the WebAPI endpoint and provide the data I need.
I would advise against using SignalR in this situtation. What you need, judging from your description, is the most basic use case of submitting an ajax request and receiving a response.
You are not designing a system where you need the server to initiate communication with the browser or anything like that, where sockets (and SignalR as an abstraction over sockets with fallbacks to less suitable protocols) is a huge overkill.
Don't worry, your use case is rather simple.
It's a little out of scope to describe how to setup a WebApi project, how to configure routing, action names, etc. Simple google searches will surely provide ample quality tutorials on getting started.
I'll just try to explain what the general idea is, with some code samples, to get you thinking in the right direction.
You need to create an ApiController.
The simplest version of that Controller will probably look something like this:
public class ShipmentVerificationController : ApiController
{
//this is the response object you will be sending back to the client website
public class VerificationResult
{
public bool Valid;
}
public VerificationResult GetIsItemValid(string BarCode)
{
bool itemIsValid;
// Implement checks against the BarCode string here
itemIsValid = true;
return new VerificationResult { Valid = itemIsValid };
}
}
Note that the inner class represents the response you will be sending back. It should be properly filled out with additional info if needed and probably put into a separate .cs file in the "Models" folder or where ever you see fit.
I have declared it inside the controller for demonstration purposes only
Once you have a WebApi service deployed, it's really easy to send it data from your website and receive the feedback.
To simplify Ajax requests, jQuery is often used.
Once the user inputs the barcode into a textbox, you can hook up an event to check for return key being pressed (most barcode scanners send the return key command after they input the barcode data) and then write something along the lines of:
var barcode = $("#input-field").val();
$.getJSON( "<url_to_your_webapi_service>/api/ShipmentVerification/GetIsItemValid/" + barcode, function( data ) {
if (data.Valid) {
// great, highlight the item as valid
}
else {
//better indicate an error with the scanned item
}
});
Please note that for simplicity I have not included any error handling, url parameter encoding, and most importantly, zero authorization.
Authorization is very important if you deploy the web service to the open web but still do not want anyone to be able to call it.
You will have to research these topics yourself, but I hope I have presented you the core concepts and logic behind a simple service such as this, so you have a base to start with.
If you come up with specific problems and questions post a new question.
I actually found a more simple way to do this. I nixed the idea of using a WebAPI endpoint and just went with a normal controller. I used ajax to prevent the page from refreshing with the new view, since that view is actually just json data with my return values in it.
Related
I am having difficulty to understand some code from GitHub (I am learning angular, however this is server side code written in c#)
The code is available on GitHub code).
I can't completely understand the very first line of code var refreshToken = Request.Cookies["refreshToken"]; Where does Request.Cookies come from? It is not a variable and it looks like a static call to some array Cookies. How does the element of that array happen to contain "refresh-token" item?
Could someone please explain this? (this code comes from the class derived from BaseController)
[HttpPost("refresh-token")]
public ActionResult<AuthenticateResponse> RefreshToken()
{
var refreshToken = Request.Cookies["refreshToken"];
var response = _accountService.RefreshToken(refreshToken, ipAddress());
setTokenCookie(response.RefreshToken);
return Ok(response);
}
When you work in an HTTP application, .NET manages some context for you. A bunch of stuff you write, like your POST action, is provided with an HTTP context, which has properties that provide information about the request. This includes headers, cookies, etc.
When you use Request within an MVC controller (or some other HTTP context) you'll get access to the HttpContext and Request that relates to the specific single request. It feels like magic, but it's the framework doing the work for you.
A bit more information on context.
You need to check other serverside codes which set the cookie,Cookie is created in serverside firstly and sent to User Agent,often stored in your browser.next time you send a request,your request may contain the cookie
you could check the codes like:Response.Cookies.Append(....)
I am trying to create a WebHookHandler for Webhooks send from WordPress WooCommerce in ASP.NET C#.
I started with creating a ASP.NET C# Azure API App WebApplication Project and adding the relevant references (Microsoft.AspNet.WebHooks.Common, Microsoft.AspNet.WebHooks.Receivers, Microsoft.AspNet.WebHooks.Receivers.WordPress). Added the WebHookConfig, WordPressWebHookHandler and registered the WebHookConfig in the GlobalAsax.
I then published the application as an Azure App Service.
My WordPressWebHookHandler is still the default of the examples and looks like this:
public class WordPressWebHookHandler : WebHookHandler
{
public override Task ExecuteAsync(string receiver, WebHookHandlerContext context)
{
// make sure we're only processing the intended type of hook
if("WordPress".Equals(receiver, System.StringComparison.CurrentCultureIgnoreCase))
{
// todo: replace this placeholder functionality with your own code
string action = context.Actions.First();
JObject incoming = context.GetDataOrDefault<JObject>();
}
return Task.FromResult(true);
}
}
When testing a User Creation WebHook in WooCommerce I can see the request in the log as below.
But unfortunately it is never received while debugging and I see below error.
I am thinking maybe I need a custom WebHook instead of the WordPress specific one as this is a WooCommerce Webhook. Or possibly it is handled wrong in the routing and ends up in another controller.
Any help is much appreciated.
Your WebHookReceiver is wrong
There is a mismatch of expecting HTML Form Data, when in fact it should be expecting JSON.
WordPressWebHookHandler is still the default
This is what is causing your error. If you look at the WordPressWebHookReceiver, the ReceiveAsync() method implementation, calls out to ReadAsFormDataAsync() method, which is not what you want, as your Content-Type is json. So, you want to be doing ReadAsJsonAsync().
Solution: Don't use the WordPressWebHookReceiver and switch it to another one that will call ReadAsJsonAsync().
Looking at the code
I am thinking maybe I need a custom WebHook instead of the WordPress specific one as this is a WooCommerce Webhook.
You had the right idea, so I dug up some of the code to explain exactly why this was happening.
The code block below is the ReceiveAsync() method that is overridden in the WordPressWebHookReceiver. You can see that it is calling the ReadAsFormDataAsync() which is not what you want...
public override async Task<HttpResponseMessage> ReceiveAsync(
string id, HttpRequestContext context, HttpRequestMessage request)
{
...
if (request.Method == HttpMethod.Post)
{
// here is what you don't want to be called
// you want ReadAsJsonAsync(), In short, USE A DIFFERENT RECEIVER.
NameValueCollection data = await ReadAsFormDataAsync(request);
...
}
else
{
return CreateBadMethodResponse(request);
}
}
A quick search through the repository for classes that call the ReadAsJsonAsync() method, shows that the following recievers implement it:
DynamicsCrmWebHookReceiver
ZendeskWebHookReceiver
AzureAlertWebHookReceiver
KuduWebHookReceiver
MyGetWebHookReceiver
VstsWebHookReceiver
BitbucketWebHookReceiver
CustomWebHookReceiver
DropboxWebHookReceiver
GitHubWebHookReceiver
PaypalWebHookReceiver
StripeWebHookReceiver
PusherWebHookReceiver
I assumed that the CustomWebHookReceiver would fit your requirements, so can grab the NuGet here. Otherwise you can implement your own, or derive it from this class, etc.
Configuring a WebHook Recevier
(Copied from the Microsoft Documentation)
Microsoft.AspNet.WebHooks.Receivers.Custom provides support for
receiving WebHooks generated by ASP.NET WebHooks
Out of the box you can find support for Dropbox, GitHub, MailChimp,
PayPal, Pusher, Salesforce, Slack, Stripe, Trello, and WordPress but
it is possible to support any number of other providers
Initializing a WebHook Receiver
WebHook Receivers are initialized by registering them, typically in
the WebApiConfig static class, for example:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
...
// Load receivers
config.InitializeReceiveGitHubWebHooks();
}
}
There is a problem with the data format that you send in your request. You must use format of HTML Form as your error message said.
Proper POST data format is described here: How are parameters sent in an HTTP POST request?
Don't forget to set Content-Length header and correct Content-Type if your library doesn't do it. Usually the content type is application/x-www-form-urlencoded.
I would like to make some additions to Svek's answer as I now got my Proof-of-concept completed and understand a bit more about the receivers.
His answer pointed me in the right direction, but needs a little addition.
WordpressWebHookReceiver
Can take in Wordpress Webhooks of type HttpPost. This does not work with Woocommerce as Woocommerce sends Json Webhook messages and will fail the HttpPost validation which is build into the WordpressWebHookReceiver class.
CustomWebHookReceiver
Can take in custom ASP.NET Webhooks. The custom ASP.NET webhooks have a specific partner for validation which includes but is not limited to the 'ms-signature'. Even adding the header will not suffice as the signature is also used in a different way from out of the box Woocommerce to encrypt the message. Basically coming to a point that you can't integrate Woocommerce with the CustomWebHookReceiver without changing the Webhook classes of Woocommerce.
GenericWebHookReceiver
This is the receiver you want, which accepts basically a generic set of Json data and will be able to use the "code" query parameter to verify the secret which you can add in the web.config of your asp.net api application. I used this receiver to finish the Proof-of-concept and got both the signature validation as well as the deciphering of the message working right of the bat.
My basic class which I will start to build into a real solution can be viewed below and changes the JObject into a dynamic object in the methods I call from the class. As you can see I have two methods currently added, one for the customer create and one for the order create to call the respective methods which do an insert into Dynamics 365 (former CRM).
public class GenericJsonWebHookHandler : WebHookHandler
{
public GenericJsonWebHookHandler()
{
this.Receiver = "genericjson";
}
public override Task ExecuteAsync(string generator, WebHookHandlerContext context)
{
var result = false;
try
{
// Get JSON from WebHook
var data = context.GetDataOrDefault<JObject>();
if(context.Id != "crcu" && context.Id != "cror")
return Task.FromResult(true);
if (context.Id == "crcu")
{
result = WoocommerceCRMIntegrations.Entities.Contact.CreateContactInCRM(data);
}
else if (context.Id == "cror")
{
result = WoocommerceCRMIntegrations.Entities.Order.CreateOrderInCRM(data);
}
}
catch (Exception ex)
{
result = false;
}
return Task.FromResult(result);
}
}
Thanks for looking!
Background
I am writing an API layer for a company that will be used by disparate apps and external consumers.
On the consumption end, most consumers will call a service via ajax using a jQuery $.post(); however, Internet Explorer makes our lives more challenging (of course!). For IE, I must use the XDomainRequest object because IE will not run a jQuery $.post() and because if I use IE's XMLHttpRequest(), I get a security message which is unacceptable (again--of course!):
Otherwise, XMLHttpRequest() works fine.
I am using C#, .NET MVC 4 (WebApi)
Problem
The problem is that XDomainRequest does not allow you to set the Content-Type header and always defaults to text-plain which MVC 4 WebApi controllers will not accept (and yet again--of course!!).
Question
How can I intercept requests for my controllers, detect the presence of text-plain content types and change them to text-json content-type on the fly?
Thanks in advance!
Well after two days and pouring over documentation and reading in this thread I've been able to make this work. So please forgive me if my description of the solution is poor; this is the first time I answer one of these types of threads. Since it took me so long to find the problem I figured it is worth saving some soul from falling into this same problem.
The source for my help came from the above link by byterot.
First thing I did was to create a DelegatingHandler. So in my helper folder or where every you want to create a class and call it what you want.
Here is mine:
public class ContentTypeHandler : DelegatingHandler
{
/** Check that this is an IE browser. */
if ((request.Headers.UserAgent.ToString().IndexOf("MSIE", System.StringComparison.Ordinal) > -1))
{
MediaTypeHeaderValue contentTypeValue;
if (MediaTypeHeaderValue.TryParse("application/json", out contentTypeValue))
{
request.Content.Headers.ContentType = contentTypeValue;
request.Content.Headers.ContentType.CharSet = "utf-8";
}
}
/** Return request to flow. */
return base.SendAsync(request, cancellationToken)
.ContinueWith(task =>
{
// work on the response
var response = task.Result;
return response;
});
}
Last think that you have to do is call the Handler in your Global.asax.cs file inside your Application_Start():
GlobalConfiguration.Configuration.MessageHandlers.Add(new ContentTypeHandler());
That's all I did and it worked. So good luck I hope this helps someone.
There is no problem modifying request in HTTP stack. It can be done by writing and registering your custom DelegatingHandler before it gets to the controller. Delegating handler can take care of this early-on in the game, so your request will arrive to the controller in the form you want it to. It could be route-specific handler as well.
http://msdn.microsoft.com/en-us/library/system.net.http.delegatinghandler.aspx
Did you try $.ajax instead of $.post ?
I am kinda new in web development, looking for secured way to update SQL Database from the client side, or in other description updating the database without refreshing the webpage like (like facebook button).
I searched a lot and found that it can be done by using a web service and call it by javascript or using javascript direct or ajax, but which is the best and secured way and there is any other way to do it ?
thanks..
you can use ajax for updating database from client side.. Like if you click a button in web page, get the click event of that page through JavaScript or jQuery then through ajax you can perform database update. See the code below:
For catching event(like my button id is button1):
$('#<%=button1.ClientID%>').click(function{
$.ajax({
type: "POST",
url: "default.aspx/UpdateDatabase",
data: "{'textboxvalue':'" + $('<%=textbox1.ClientID%>').val() + "'}'
contentType: "application/json;charset=utf-8",
datatype: "json",
success: UpdateDone
});
});
In above code you have passed one value from a textbox1 to function UpdateDatabse in Default.aspx page(Please defined this function as [WebMethod]). then do your update in this function and return some string or bool value so that you can judge that update is done then value in success is name of function that will run if your function runs successfully so define that function in JavaScript or jQuery like
function UpdateDone(response)
{
if(response.d == 'done')
{ alert('Update is done'); }
else
{ alert('Sorry Update not done'); }
}
Above code will not do any postback you see that your value is updated in database. Please note that the function you make in C# page please mark it as WebMethod and it will be a static method, then only your JavaScript can find that function.
Hope this will resolve your problem.
The term ajax you use is correct but already a bit old. The new kids on the block are called SPA's where SPA stands for Single Page Application
It does what you want to achieve to the extreme: no more page refreshes. So it seems a good way to start
Here is The ASP.NET Single Page Application homepage
My advice is to research and invest time in one of the (many) javascript frameworks that will help you achieve this goal much faster. Hand coding javascript and make it work cross browser is too much work. The ASP.NET team choose upshot.js to solve your problem and it seems a fine choice.
Screenshot take from here
I found doing AJAX with JSON with ASP.NET MVC 3 to be easiest method of doing AJAX requests. Then you can have a specific action method that handles the request and makes the updates the database via Entity Framework(EF).
Essentially only passing the data that needs to be updated in the JSON. From there the MVC Action receives the JSON, and uses EF to lookup the DB record, apply/save changes. It can even respond with a success message which your AJAX can use to update some field that verifies the data was saved for the user(you could even do something where you have a "Saving..." message appear between the first ajax request and the response.)
This will allow you to send the request without refreshing your page. All your DB access code will be server side in the Action method.
This example shows how you might do a json request. You would modify this by adding additional code to the Create method to interact with entity framework(or your database tool of choice) to update a record based on the Person person parameter that was passed in(notice MVC did a really nice thing of converting the json data into a nice Person class!)
http://juristr.com/blog/2011/08/posting-json-data-to-aspnet-mvc-3-web/
If the data the user will enter in the webform is sensitive, you would need to encrypt it before sending the json request. I would personally just setup the website to use SSL. Anything you cook up on your own probably won't be as secure as SSL.
The code you add to the Create method might look like this:
//Find the person that they are attempting to edit
Person currentPerson = db.Persons.Find(person.PersonKey);
//update the database fields based on the submitted data(I would probably actually use AutoMapper for this
currentPerson.Name = person.Name;
currentPerson.DateOfBith = person.DateOfBirth;
//etc.
db.SaveChanges();
//compose a JSON response object indicating success, you would want to combine this with a try catch in the above to reply regarding failures as well
I've made a little game in silverlight that records users scores whilst they play.
I decided it would be a lot better if I could implement a leaderboard, so I created a database in mySQL to store all the high scores along with names and dates. I have created some communications to the database in ASP.net. This works and I can simply insert and get data within the code.
It's now time to link the silverlight project with the ASP.net database communications, so I can send the users name and score as variables to my ASP.net code and then it will upload it to the database. That's all I need. Surely there must be an easy way of doing this, I just can't seem to find any ways when researching.
Thanks in advance,
Lloyd
At first you need add Generic Handler to your ASP.Net project.
public class Handler1 : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string userName = context.Request["user"];
int score = int.Parse(context.Request["score"]);
//And store it in DB
}
}
After you need call this handler from SilverLight app:
string uri = HtmlPage.Document.DocumentUri.ToString();
// Remove the web page from the current URI to get the root URI.
string rootUri = uri.Remove(uri.LastIndexOf('/'),
uri.Length - uri.LastIndexOf('/'));
string diggUrl = String.Format(rootUri + "/" + "test.ashx?user={0}&score={1}", "testuser", "234");
// Initiate Async Network call to Digg
WebClient diggService = new WebClient();
diggService.DownloadStringAsync(new Uri(diggUrl));
here i used Uri Class to send parameter to asp.net, but you can send string format only.
// this code written on Silverlight Button Click Event.
Uri myURI = new Uri(HtmlPage.Document.DocumentUri,String.Format("Report.aspx?brcd={0}&acc={1}&user={2}", Brcd, Acc, User)); HtmlPage.Window.Navigate(myURI, "_blank");
below code is written on Asp.net page_load or page init event
Brcd = Request.QueryString["brcd"];// brcd value accept here.
acc= Request.QueryString["ACC"];`
user= Request.QueryString["User"];
in above code we accept the silverlight parameter in asp.net but in [] bracket put name as it is use in silverlight page because it case sensitive.
By ASP.NET, do you mean an ASP.NET Webforms app?
If so, an ASP.NET Webforms app is a method of building a UI. What you need is an API, for your Silverlight app to use programatically. For this purpose you may want to consider building an ASP.NET Webservice instead, which provides an API over HTTP.
What do you need its to send data to web server from a Silverlight application, right?
You can:
Call Javascript functions from Silverlight and, there, do a postback
Call web services with Silverlight, but make sure its in same server which your SL application came from, or you will face some XSS issues.
An easy way to do this is to have your Silverlight code create a REST URL by encoding the information into the query string, and invoking an .aspx page on the server. The page wouldn't need to return any markup; it would just handle the back-end stuff and return.
Alternatively, you could make a web service call from Silverlight to your back end.
I prefer the latter approach. It's a little more work the first time through, but it's also more general purpose and makes for generally better code in the long run.
Although technically you could use JavaScript, I wouldn't suggest it; why go backwards in tech if you don't have to?