Passing Model sub-tables to HTTPPOST Controller for Model Editing - html

I have created a MVC 5 application where I am creating a custom purchasing system.
My View model is generated based on the contents of an SQL Database. The database uses a Single Primary Key for a Purchase Order with some basic data. In addition to the basic data each PO can have multiple items within that purchase order. This creates a relationship where there can be N items to a single Purchase.
When I am doing a form Submit the sending of the Purchase Order specific information, ie using TextBoxFor(m => m.Date), works fine. However I cannot seem to pass the list of all the Items within it. For example when I am doing #Html.TextBoxFor(m => m.Details.ItemName) it is not populating the section in the model during the POST.
I have tried sending all the information using #Html.TextBoxFor(m => m.Details) but it throws errors as the TextBoxFor cannot handle these data types.
I am after a system where I can edit a purchase order model by adding or removing items without committing to my database until the 'save' button is pressed.
My View Model example is
public class PurchasingEditModel
{
public tbl_PurchaseOrder PurchaseOrder;
}
Purchase order in itself has a link to PurchaseOrderDetails (within SQL) via a Foreign key reference of the Purchase Order. This creates the Many Items to One PO.
The controller for the edit page is
public ActionResult Edit(int? pkPurchaseOrder)
{
model.PurchaseOrder = db.PurchaseOrder.Where(x => x.pkPurchaseOrder == pkPurchaseOrder);
return View(model);
}
This together with a standard Edit.cshtml using #Html.TextBoxFor(m => m. all works fine with the display portion, until I want to post the multiple items within the sub-table.
Really the easiest way for me to handle this would be to pass the all contents of model during the display, which has all the elements of the items within the PO, to the POST function.
Any guidance you can give is appreciated.

I have solved my own issue, which makes a change...
To POST the data within a sub-table(IQueryable) Ive had to do the following
Within my main html code add
#foreach(var item in Model.PurchaseOrder.tbl_Details)
{
#Html.Partial("_POItemDetailsPartial", item)
}
Then Ive had to create a MVC Partial Page (Razor) named _POItemsPartial.
Within that page I have put the following..
#using (Html.BeginCollectionItem("Model.PurcahseOrder.tbl_Details")
{
#model ModelSpace.Model.tbl_Details
#Html.TextBoxFor(m => m.Description)
}
When the POST action occurs I now get the description for all the 3 items I have within the PurchaseOrder.
**
UPDATE:
**
Despite getting this data..I am now losing all my original model data such as Total Price it seems that the Partial Call being passed the Model.tbl_Details is only passing that information and clearing the rest.
When it returns it ends up with all higher level data removed. If I comment out the partial call it all comes back.
Turns out I still need help.... :(

Related

Do not change the router values ​in the address

I have a page (index) with an #ActionLink that opens another page to edit an invoice, the page will appear correctly, but the [Url-address] shows the number for the invoice, and when I change the number for the invoice in the [Url-address], it means that he opened another invoice, and I want the modification page not to open from By modifying the [Url-address] or using a direct link, I found a nice way, but it is used with [Post] and not Get. Is there a way to protect the [Url-address] of the page from being modified and its values?
View Index:
#Html.ActionLink(
linkText: "Edit_Invoice",
actionName: "Invoice_Edit",
controllerName: "Invoice",
routeValues: new { ID_Invoice = 2 },
htmlAttributes: new { area = "Pro"})
Controller :
[HttpGet]
public ActionResult Invoice_Edit(int id_invoice)
{
Table.Invoice invoice = (from i in Cn.Invoice
where i.ID_Invoice == id_invoice
select i).FirstOrDefault();
return View(invoice;
}
View Invoice_Edit:
#Html.TextBoxFor(m => m.ID_Invoice)
#Html.TextBoxFor(m => m.Date_Invoice)
<button>save</button>
When you open the invoice modification page, its number will appear in the address as in the link below
https://localhost:44320/Pro/Invoice/Invoice_Edit?ID_Invoice=2
I only want to open invoices that are selected from the page only.
Update 1 : Change Title Answer
if you what users to open only invoices that they are allowed to open, antiforgery token has nothing to do with it. You neeed server side validation, authentication and authorization. All of these should be implemented on the server side. Client side javascript code is not enough.
Anti-Forgery Tokens don't make a lot of sense for any request where you're not modifying and persisting data. So I recommend to remove [ValidateAntiForgeryToken] from your GET since GET request will be returned to the user, not the attacker.
AntiForgeryToken is designed for POST requests and it expects the token in Request.Form collection. You can just use post instead of get to receive data. Or you can use ajax. Google and you will find some examples.
But make sure that you are using them when you're creating, updating or deleting data.

2sxc - One content-type, one list view, one cshtml, some rows not shown

Using 2sxc to create a new app with only:
- One content type
- 15 rows of data
- One view (razor, single cshtml file)
When I call the #foreach loop, only some of the data is shown in the list view (apparently the ones inserted in the current dnn module and only through the "new" button in the toolbar). If I add the row in the admin panel, it will not show. When I deleted the module and inserted it again, I can see the data in the admin panel, but not in my list view.
Attached screens.
I tried calling the data with:
#foreach(var Content in AsDynamic(Data["Default"])){...}
or
#foreach(var e in List.OrderBy(e => e.Content.Farmaco).Where(e => e.Content.Cat == "1")){
var Content = e.Content;
... }
but the result is the same.
Am I missing something really obvious?
DNN 9.1.1
2sxc 9.04.01
https://drive.google.com/file/d/0B-4bmuuNWVx2MUxxa0g1SExqUkE/view?usp=sharing
Yes, you're clearly not familiar yet with "raw data" and items-assigned to a modules.
In our code you get the module-data with Data["Default"], whereas the raw-data you would get from a query (then also with Data["Default"] or Data["Whatever-Name-Your-Stream-In-Your-Query"])
If you want to work with all data, you would again use a query, or App.Data["TypeName"] and build on that.
Check out http://2sxc.org/en/blog/post/12-differences-when-templating-data-instead-of-content

Can't save the data using wbragancia widget yii2 for more than one dynamic form in single view

I am new in yii2 and i am using wbraganca/yii2-dynamicform widget in my view. My question is that I have to use more than two dynamic form in a single view. For single dynamic widget it works fine while saving from controller but others are saving just the last data of dynamic widget, while inspecting the post data in network array index for others except first dynamic form are not increasing (there index is only zero). Would you please suggest how should I have to do. How can I use multiple dynamic-form widget in single view. Thank you in advance.
I believe the problem must be in your view. You should ensure that each control has a unique name and then loop through the post variables in the controller.
<?= $form->field($modelx, "[{$i}]MyVariableName", ['labelOptions' => ['label' => false]])->textInput(['name' =>'myClassNameHere'."{$block}[$i][MyVariableName]"]) ?>
See the 'name' option in the code above. It gives a unique name to each field. Here the $block variable is a unique code I append to each widgetItem class in the DynamicFormWidget.
If I now look at my POST data, I see something like the following:
myClassNameHere0[0][MyVariableName]:1
myClassNameHere1[0][MyVariableName]:11
If this does not help - post a simply example that you cannot get working and I will have a look at it.

Make grails pagination

My controller returns results in a Array like this:
render (template: 'show' , model: [changes: changes])
Show is a default action and changes is an Array created with a query(createCriteria).
How can I make pagination in my index.gsp page which is displaying results in a HTMl div?
My problem:
Controller:
def list() {
[terminHistorie: changes, terminHistorieCount: changes.size()]
}
gsp:
<g:paginate controller="terminHistorie" action="list" total="${terminHistorieCount}"/>
Error: Tag [paginate] is missing required attribute [total] at C:/Users/matejb/Documents/NetBeansProjects/gutmann/grails-app/views/terminHistorie/index.gsp:309
The way pagination works is you first need to create a view using paginate tag, then on your show action you need to slice your changes. Meaning that the view will send the offset and max parameter and your createCriteria will query the database only for those data. Take a look at this page and then here to see how you can pass max and offset into your createCriteria method.
To see an example, see this page or create a new application with one simple domain and generate scaffolding for it. Grails will generate a paginated result for you.
Btw, if you are using ajax you might want to use remote paginate plugin.

How can I filter choices out of a drop down list when using Dynamic Data?

I feel like this should be easy, but I don't see any way to do it.
I'm using ASP.NET Dynamic Data with Linq to SQL. I've got a table with an Association to the Technician table. The Parent Property is TechAssignment, and on the web form I'm using a DynamicField to display it.
This works fine really, it correctly sees it as a ForeignKeyField and uses that template to give me a dropdown with a list of techs from the Technicians table.
The only problem is that it gives me a list of ALL the technicians, when there are quite a few who are inactive. How can I tell Dynamic Data to filter out inactive technicians so they can't be selected?
LINQ to SQL generates partial classes.
Add a new property (copy from the other foreign key property)
Apply the filter in the get (either by LINQ2SQL or filtering the original property)
Bind to that property
Example UnapprovedContacts in Association table
public partial class Association
{
public IList<Contact> UnapprovedContacts
{
get
{
return Contacts.Where(c => !c.IsApproved).ToList();
}
}
}