How can I implement this type of redirect after post method in MVC - asp.net-mvc

I am currently creating an MVC application that is currently getting a value from a post from a webhook. I think that the problem is that the application is getting the value from the POST verb but then it is not displaying it because the Get verb is being used to display the View so both Verbs are counter acting each other.
The webhook will fire A Json payload to my application successfully because I have code in it that will send the Json payload in a variable via email to my email account.
Dim body = issue.issue.key
mail.Body = body
That is in a try catch block because in order for it to have a value it must have a value in it and the application will perform the GET first, so there is a null value in the body variable, then it does the POST to get the value but it will not display the value, refreshing will just perform the GET preventing it from being displayed. How can I perform both actions at the same time so I can display a value in a ViewBag for example.
ViewBag.response = status + key
This is the type of structure that I would like to implement to try and fix the error but I do not know how to complete all of the steps:
This is what I have got so far:
The POST is coming in from a webhook and I am reading it like this.
Dim reader As System.IO.StreamReader = New System.IO.StreamReader(HttpContext.Request.InputStream)
Dim rawSendGridJSON As String = reader.ReadToEnd()
Dim tempVar As Rootobject = JsonConvert.DeserializeObject(Of Rootobject)(rawSendGridJSON)
System.Diagnostics.Trace.TraceError(rawSendGridJSON)
I am then trying to store the post values in a table like this:
Public Function CallBack(tempTable as temporaryTable)
Dim tempVar As Rootobject = JsonConvert.DeserializeObject(Of Rootobject)(rawSendGridJSON)
tempVar = temporaryTable.tempVar
I then save the new items in the actual table in the database, then I try to display it in a view on another page. This is not working correctly and the problem lies with this line, as the post is not being correctly read in at the right time. (The value is processing correctly as I can use an email method to send the variables in an email back to the application but this application needs to be real-time efficient code).
Is there a better way to use this method and how can I invoke this process that I want to do properly so that I can display the correct information?
Update
To clarify, there are two posts that are happening, the first one is when the user enters in information and submits it. This is then stored in a database and send to JIRA via email. Once JIRA receives the information, it is sends a HTTP POST webhook JSON Payload back to my application with updated information. I then have deserialized the JSON Payload into a variable called issueKey.
The problem is that on the View page that the information is sent to will automatically display a null value first before the value is sent to it, I want the application to work so that it will actually display/store in a database the values from the Webhook JSON Payload but I cannot figure out how to display the values.
I have now set up a communication channel from SignalR to my MVC application, at the moment it is being received by the MVC and I have set up a SignalR chat Hub in my MVC application, but I don't know how to integrate them, how can this be done?

As I understand it, there are two flows at work here. The user posts data, which triggers an email to Jira. Then sometime later (usually quite fast, but not always) JIRA triggers a webhook in the web application with some updated information, and you want to display this updated information to the user somehow, or at least inform the user when the updated information comes back from JIRA.
I would implement a standard Post-Redirect-Get for the user initiated part (as per br4d's comment). I.e. a post to store the data in the database and send email to jira, which returns a redirect to a get which shows the data stored in the database.
Now for the other part I would use signalr to set up some sort of communications channel to the user. The webook could then send a signal (of sorts) through the communication channel to the users browser and either display the data, or trigger a refresh of the page (if you are updating the database with data from Jira).
It is unclear if you are doing straigt mvc, or some sort of SPA application, but it is not really important. The users browser has no way of knowing about the webhook (which is a part of the webapplication and unrelated to the users session), and you need some sort of communication between the webapplication and the browser, and for this signalr is very very good.

Related

How to get line items from Business Central Web Service (Odata)?

From Microsoft Documentation, to get salesOrderLines, the following http request is needed:
GET businesscentralPrefix/companies({id})/salesOrders({id})/salesOrderLines({salesOrderLineId})
However, it assumes each json object has a unique GUID. But when I try to get Odata, the only thing close to a unique id I get back is "#odata.etag", and this does not allow me to access the salesOrderLines.
Use /salesOrders?$expand=SalesOrderSalesLines

What is the difference between new sap.ui.model.odata.ODataModel and read?

I am playing around with a OData service and I am very confused when to use this
var oModel = new sap.ui.model.odata.ODataModel("proxy/http/services.odata.org/V3/(S(k42qhed3hw4zgjxfnhivnmes))/OData/OData.svc");
this.getView().setModel(oModel);
vs
var oModel = new sap.ui.model.odata.ODataModel("odatserviceurl", true);
var productsModel = new JSONModel();
oModel.read("/Products",
null,
null,
false,
function _OnSuccess(oData, response) {
var data = { "ProductCollection" : oData.results };
productsModel.setData(data);
},
function _OnError(error) {
console.log(error);
}
);
this.getView().setModel(productsModel);
I have two working example using both approach but I am not able to figure out why using read method if I can achieve same with first version. Please explain or guide me to the documentation which can clear my confusion.
Ok, lets start with the models:
JSON Model : The JSON model is a client-side model and, therefore, intended for small datasets, which are completely available on the client. The JSON model supports two-way binding. NOTE: no server side call is made on filtering, searching, refresh.
OData Model : The OData model is a server-side model: the dataset is only available on the server and the client only knows the currently visible rows and fields. This also means that sorting and filtering on the client is not possible. For this, the client has to send a request to the server. Meaning searching/filtering calls odata service again.
Now, lets look at scenarios where we will use these models:
Scenario 1: Showing data to user in a list/table/display form. Data manipulation is limited to searching and filtering. Here, I would use oData model directly to controls as only fetching of data is required.( your method 1) (NOTE: One way binding). Remember here all changes require a call to server.
Scenario 2: I have an application which has multiple inputs, user can edit changes, also some fields are calculated and mandatory. All in all, many user changes are done which may be temporary and user might not want to save them. Here, you dont want to send these temporary changes to backend as yet. You way want to manipulate, validate data before sending. Here, we will use JSON Model after reading data from odata model ( your method 2). Store the changes in local JSON model, validate and manipulate them and finally send the data using Odata create/update. Remember here all changes DO NOT require a call to server as data is present in local JSON MODEL.
Let me know if this helps you. :)
EDIT : Additional Information :
As per your comment :
Documentation says oModel.read' trigger get request but new sap.ui.model.odata.ODataModel("proxy/http/services.odata.org‌​/V3/(S(k42qhed3hw4zg‌​jxfnhivnmes))/OData/‌​OData.svc")` does the same thing so why and when to use oModel.read
Here, is where you misunderstood. The code
new sap.ui.model.odata.ODataModel("proxy/http/services.odata.org‌​/V3/(S(k42qhed3hw4zg‌​jxfnhivnmes))/OData/‌​OData.svc") will NOT send a read/get Request. It calls the odata services and fetches the metadata of the service. A service can have multiple entities.
For example: the service :http://services.odata.org/Northwind/Northwind.svc/ has mutiple entity sets such as Categories, Customers, Employees etc. So, when I declare : new sap.ui.model.odata.ODataModel("http://services.odata.org/Northwind/Northwind.svc/") it will fetch the metadata for service (not actual data). Only when you call the desired entity set, it will fetch the data. The Entity set is specified :
When you call the read method ( like you have specified '/Products')
Bind the entity set name directly to control like to List,Table etc ( items='{/Products}' )

Grails pass object to the view and back again

I have some data that I need to persist through multiple actions within my Grails app. Due to the nature of the data, I would prefer not to store the data in the session. Here is an example of what I would like to do.
class MyController{
def index(){
MyObject object = MyObject.new(params.first, params.second, params.third)
[gspObject:object]
}
def process(){
MyObject object = params.gspObject
//continue from here
}
}
In my GSP if I do
<g:form action="process" params="[gspObject:gspObject]">
Then I get the error
Cannot cast object 'net.package.MyObject#699c14d8' with class 'java.lang.String' to class 'net.package.MyObject'
My question is, If I want to get the object back that I sent to the gsp, how can I get that? Is there some kind of scope that I can save the object in that would be a little safer then session? Is there a way to pass the object into the page itself and pass it back in the next request?
Grails has many layers, but at the bottom you have plain old HTTP just like in any web app. It's a stateless protocol, and you send a text or binary response, and receive text or text + binary requests. But you can't expect to be able to send an arbitrary object to a web browser in HTML and receive it back again in the same state as when you sent it - where is this Java/Groovy JVM object going to be stored in the browser?
You have basically two options. One is to store it at the server, which is less work because it remains as the same object the whole time. The session is a good location because it's coupled to the user, is created on-demand and can automatically time out and be removed, etc. The other is to do what you're trying to do - send it to the client and receive it back - but you are going to have to serialize it from an object (which could be a complex object containing arbitrarily many other objects) and deserialize it from the format you used on the client back into Java/Groovy objects.
JSON is a good option for serialization/marshalling. You could store the stringified object in a hidden form element if your page uses a form, or in a querystring arg if you click a link from this page to the next in the workflow. Don't send all of the object's data though, only what you need to rebuild it. Anything that's available in the database should be referenced by id and reloaded.
Something like
[gspObject: object as JSON]
or
[gspObject: [first: object.first, first: object.firstsecond, ...] as JSON]
will get it in the correct format for sending, and then you can parse the JSON from the request to reinstantiate the instance.

Facebook returning random string instead of "state" param

I am using Omniauth for Facebook connect in a Rails app. Facebook auth connects properly, but the "state" param - through which I should be able to pass data to retrieve on callback - is returning a string I can't decipher.
For example, authorizing through "/auth/facebook?display=popup&state=19422"
ends up returning a state of "ecae4f444fb248944083db0623c9a86f3f75dff36006be7e"
Any idea why this is happening?
The state param is not supposed to be used to pass data around. That param is only to be used to stop CSRF vulnerabilities. That randomly generated string is being used in background to prevent those types of attacks.
You can pass your custom data by simply using any other param. OmniAuth is already kind enough to persist in the session any extra params you may send in your request.
So instead of passing data with
request_url?state=data
and getting it with
data = params[:state]
You can pass it with
request_url?whatever=data
and get it with
data = request.env['omniauth.params']['whatever']
And you can even omit the request and get the data with:
data = env['omniauth.params']['whatever']

Cancelling NSJSONSerialization - Search as you type, requests overlapping

Similar to the iPhone Facebook app search function, I am implementing search as you type functionality into my application although I have a problem when decoding the data into JSON format.
Basically what happens is because some searches take longer than others, they return at different intervals and this causes some small visual issues when the data is presenting on the screen.
I have set an NSLOG after each decode using NSJSONSerialization for the keyword 'industry'
2013-04-09 23:38:18.941 Project Name [42836:1d03] http://fooWebAddress/json/?method=search&limit=10&q=indus
2013-04-09 23:38:19.776 Project Name [42836:3e07] http://fooWebAddress/json/?method=search&limit=10&q=indu
2013-04-09 23:38:20.352 Project Name [42836:8803] http://fooWebAddress/json/?method=search&limit=10&q=indust
2013-04-09 23:38:21.814 Project Name [42836:4e03] http://fooWebAddress/json/?method=search&limit=10&q=industr
2013-04-09 23:38:23.434 Project Name [42836:8803] http://fooWebAddress/json/?method=search&limit=10&q=ind
2013-04-09 23:38:24.070 Project Name [42836:7503] http://fooWebAddress/json/?method=search&limit=10&q=industry
As you can see it is all out of order.
Does anyone have any way of stopping NSJSONSerialization for the previous connection.
Or possibly any other way to go about this problem?
Steps up to NSJSONSerialization...
NSURLRequest (initwithURL)
NSOperationQueue
NSURLConnection (asynchronous)
NSJSONSerialization
Thanks in advance.
When the user starts typing more text, you could cancel your previous connections and ignore any further delegate callbacks you receive from them. Then make the new request for the current text.
You can do this by maintaining some sort of lastRequest or lastOperation reference. When the user starts typing, call [self.lastRequestOrOperation cancel] and ignore any further notifications from that request with a check like if (request != self.lastRequest) { return; } in whatever callbacks you have.
However this has the problem that if the user keeps typing for a while you are constantly cancelling requests and they may not see any results until they have stopped typing.
A better solution would be to add sequencing so that each request is associated with an increasing sequence ID. You then only parse the result and update the UI when the sequence of the response is higher than the last one you received. If you receive any out-of-band responses from earlier, you just ignore them.
This is a much more complex issue than just being able to cancel the NSJSONSerialization. My suggestion is to use NSFetchedResultsController to populate your table view that shows the search results. Use the search term as one of the predicate variable in the NSFetchRequest attached to NSFetchedResultsController. And then, when you parse the results using NSJSONSerialization, store the results with the search term associated with that request. As soon as the search term changed (which you can detect when the user types more characters), re-create the NSFetchedResultsController and reload your table view. In addition, you can also try to cancel the call to parse the previous results if you launched it using performSelector:withObject:afterDelay. Beware that this cannot be always relied upon as the call may have been initiated by the time you are trying to cancel.
Kinda basic, but you could always maintain an nsdictionary of sub-classed NSURLRequests (sub-classed to provide a tag).
Start request - add request to dicationary with tag = array.count - 1, with key matching tag
Connection returns - is the request the most recent request, if so, parse json
Parse JSON - is the request the most recent request, if so, show results, if not, only display if there are no previous results displayed
Request handling - remove key from dictionary
most recent request = does the dictionary contain an object with a higher key value
Currently what you are doing is, you type each character and calling web-service. Why to call web-service for each letter you type. If user is type continuously, then it will increase the load, so call the web-service only when user stops for a particular interval of time. and then pass that string to call web-service or what ever method you are calling.
[NSObject cancelPerformSelectorsWithTarget:self]; // This will cancel your all req which is going to make when user typing without stopping
[self performSelector:#selector(sendSearchRequest) withObject:searchText afterDelay:0.1f]; // This will pass the string to call a web-service method, on which user hold for some time.

Resources