ASP.NET Web API and Async Methods - c#

I'm working on a server-side project with a database with 2 tables:
tbl_Search and tbl_Provide
Here is some more info:
tbl_Search = table for users that search for items.
tbl_Provide = table for users that provide items.
So obviously I have 2 methods: Search() and Provide().
By calling Provide(), the user and the item are registered in tbl_Provide.
By calling Search(), the user is registered in tbl_Search as well as searching for the item he's looking for in tbl_Provide.
Now, since those methods involve database access, I decided to run them asynchronously so they won't block the main thread.
Also, each user has a rank.
My problem:
2 users or more would like to have the same item. In such situation, the user with the highest rank should be the one to have it.
Therefor, once the user finds the item he was looking for, he can't simply take it as there might be another user with a higher rank who should have it.
I'm kind of lost here, not sure how to solve it.
Thanks in advance.

Related

Getting LUIS entities inside a child dialog

I'm developing a bot using Bot Framework, LUIS and ActionBinding.
In one of my intent handlers I call a new Dialog which has the methods StartAsync(IDialogContext context) and ReceiveMessageAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
As I understand it, the messages typed by the user while waiting (with context.Wait(ReceiveMessageAsync)) won't be sent to LUIS, right?
So if I need to understand what the user is saying without having to parse the string, which are my options? Could call the ILuisService.QueryAsync with the message.Text for each message be an option?
I want to be able to detect entities typed by the user so I can map them to missing fields. For example in this conversation:
User: I want to book a flight. // LUIS detects intent
Bot: Ok. Can you tell me more about your flight? // child dialog is called to handle the rest of the conversation
User: I want to go to Madrid.
Bot: To fly to Madrid you can choose between company A, B or C.
User: I want to go with A tomorrow night
Bot: Ok, searching for available tickets for tomorrow night in A...
In this case there are no initial entities when the intent is detected, but there could be, and in that case the bot would not ask for the already given information.
For my project, a simple Form with one to one question-answer is not enough. I also need to make more validations and confirmations on previously set parameters if the user wants to change one or more parameters (i.e., I need to go back to all parameters and check if the changed parameter affects them). For example:
User: Wait, I want to fly to Barcelona instead.
Bot: Company A does not fly to Barcelona. You can choose between C and D.
User: Ok I want to fly with C.
Bot: There are tickets available for tomorrow night in company C. Keep the flight for tomorrow night?
User: yes.
Any tips or guidance for best practices would help a lot.
Thanks in advance.
Edit:
With the Sub Action solution, where would my validators operate? On the FulfillAsync method? I'd need to validate and then send a question to the user and understand the reply he sent (parsing entities). Would that be possible inside a LuisAction?
I'd like to use the QueryValueFromLuisAsync but after looking at it, I'd need to pass the paramName, which is one of the action properties (if i'm not mistaken) and that is what I'm trying to avoid. I don't want to map one answer (i.e., message.Text) to one field, i want to map one answer to multiple fields.
Let's say i need to fill a model that has 6 properties. If the bot asks one question to the user and in his reply there are 3 entities I want to map those entities to 3 fields and only make questions about the remaining non mapped fields afterwards.
My first reaction to this is to avoid using a custom child dialog and go with SubActions and create your own validators if you want to have complex logic there or even override the IsValid method from the sub action.
However, if that's not a possibility, then I would consider reusing the QueryValueFromLuisAsync method, where the action should be the model you want to interact with. That function will end up calling LUIS and will try to assign the result or return another intent/action depending on the scenario. I would give this a try.

Using the Command-Query Separation principle in MVC Controllers

I like the idea of Command Query Separation but can't see how to use it within an MVC Controller action which is adding an entity, and needs the new entity's ID after adding it.
For example, in the simplified example below a service is used to create a new item:
public ActionResult Assign(AssignViewModel viewModel)
{
var newItem = _AssignItemService.AssignItem(viewModel.ItemName, viewModel.ItemValue);
return RedirectToAction("ListItem", new {id = newItem.Id);
}
But when I redirect to the action which is going to display the new item, I need to know the ID of the newly created item, in order that it can be retrieved from the database. So I have to ask the service to return the newly created item (or at least, its ID).
In pure CQS, a command has no return value, so the pattern above would be invalid.
Any advice gratefully received.
I think you're stuck on a pedantic point.
A query is when you want to ask the database a question, like "How many customers west of the Mississippi purchased red colored items during the month of June?" That's a query. Returning the ID during an insert is not a typical query, per se.
As with most other things in software development, this pattern is not an absolute. Even Fowler says he's willing to break it when it is convenient to do so:
Popping a stack is a good example of a modifier that modifies state.
Meyer correctly says that you can avoid having this method, but it is
a useful idiom. So I prefer to follow this principle when I can, but
I'm prepared to break it to get my pop.
If you really want to retrieve the most recently-added ID from a database separately from its insertion, you can use something like Scope Identity. But I think you're adding complexity for no additional benefit.
You should pass to AssignItem method an instance of "Item" (or whatever your entity's name is) that is created from the viewmodel's values, then the method doesnt have to return anything, instead it will just update entity's Id property making it a Command method.
You can then use entity.Id for anything you want
The way to do that would be to make the caller specify the ID for the new entity (which most likely implies using GUIDs as the key).
However, in my experience, imposing the (purist) rule that a command may not return a result is going to cause problems for little gain.

Can I assume that the order I send values over POST will be model bound to an array in the same order in Asp.net MVC?

I'm am working on having a screen that allows the user to change the order of items, and when the user clicks on the "Save" button my javascript will look at the order of <li> items, and in the order it finds them it will form an array with an id value and send it back to my application. I expect the POST data to look like:
stepIds=5&stepIds=2&stepIds=1
This means that the steps are in the order of #5, then #2, and lastly #1. In my Asp.Net MVC application I plan to catch it with:
public virtual ActionResult Reorder(short[] stepIds) { }
My question is, will Asp.net MVC ALWAYS form the stepIds array in the same order that values are specified in the POST string, or do I need to do a more complicated POST in order to ensure the order the user picks is the order the server sees?
No, you cannot rely on the order. The way this is implemented in ASP.NET 4.0 it will indeed preserve the order but this might change in future versions. You may look at the HttpValueCollection.FillFromString private method with Reflector to see how it is implemented.
The only reliable way to guarantee order is this:
stepIds[0]=5&stepIds[1]=2&stepIds[2]=1

Monotouch: send data back down the stack to another ViewController

I have a question concerning Monotouch.
The situation: I have 2 ViewControllers. The first (let's call it VC-A) looks similar to the contacts edit screen, meaning it has a TableView with multiple Sections each containing Buttons and TextFields. Now when the user clicks one of these Buttons, he will get to the second ViewController (VC-B), which displays a TableView containing data from the database. When the user clicks on any of these rows, VC-B will be closed and i want to display the selected database entry (string) as the title of the Button (in VC-A) which opened VC-B in the first place.
When I did an objective-C project last year, I managed to send data back down the stack by using delegates, but I haven't found a way yet how this works in Monotouch.
I have read several questions here on SO about using the AppDelegate or using singletons, but I'm not sure that this is the right way of returning data from a subview.
You can kind of copy the delegate pattern. Add a C# delegate to your VC-B that takes one parameter, some data structure.
In VC-B's "ViewWillDisappear", call the delegate it it is not null and pass the data on to it.
This way, your calling VC can get acces to the data but you don't need tight coupling between the two controllers. All it has to do, is register a delegate-method in VC-B.
As MonoTouch is .NET4 you can use Func<MyDataStructure> or Action<MyDataStructure> and don't need to use full qualified delegate types.
I have a static singleton class that I use to store "state" type data about my app - current settings and selections that are needed in many different places in the app. That's one way to approach this.
You could also pass VC-B a reference to VC-A when you create VC-B, so that it can explicitly access it's parent view and pass back values that way.
I actually prefer to use TinyMessenger for cross container calls I find this to be very very useful when you don't want to keep references to your heavy viewcontrollers around which could potentially result in memory leaks!
var messageHub = new TinyMessengerHub();
// Publishing a message is as simple as calling the "Publish" method.
messageHub.Publish(new MyMessage());
// We can also publish asyncronously if necessary
messageHub.PublishAsync(new MyMessage());
// And we can get a callback when publishing is completed
messageHub.PublishAsync(new MyMessage(), MyCallback);
// MyCallback is executed on completion
https://github.com/grumpydev/TinyMessenger

Many-to-Many Databinding in LINQ

I've looked all over and haven't been able to find a clear answer to a seemingly common question: How can I do two-way databinding over a many-to-many relationship in ASP.net?
I have the following database structure:
I am currently writing a page for editing or adding a User record. Databinding things such as name and password is simple, but what I really need it to be able to display a list of all PhoneGroups and choose one or more from the list. How do I do this?
I tried a CheckBoxList, but while I can display the list of PhoneGroups, How do I bind the Checked state of each box based on whether the user has access? Some solutions use a loop in the OnDataBound event of the CheckBoxList. If I do this, how do I update the database when the checked state changes? I could go the brute force approach and write code to do this, but isn't there something that can make this simpler? It seems like such a common scenario.
Update #1
I am currently using Devart's LinqConnect, but I am open to change. The backend database is MySQL.
Yeah it is a common scenario and binding to that event is the solution i see used.
It is fairly simple when you consdier what the code is doing int he background. You could write your own custom server control, but thats a lot more difficult.
MVC may offer you an alternative ...
really why not redesign and only return the objects that they ahve permission for?
as for updating items in the database you need to say more about the architecture. But ultimatley to update an item you have to take the new item ... you have to do womthing like this
public void StoreTheUpdatedData(YourBusinessObject theBusinessObject)
{
var yourDataContext = new DataContext()
var oldObject = (from i in yourDataContext.YourbusinessObjects
where (blah equals blah to select your item and only your item)
select i).First();
//repeat for all properties in the object
oldObject.Property = theBusinessObject.Property;
yourDataContext.SaveChanges();
}
code liek that is what you need to do the update.
the save method varies depending on which ORM you are using ... I think linq2SSql uses commitChanges for instance. Been a while since i used that one.

Categories