How to open cshtml file in new tab from controller's method? - asp.net-mvc-3

I'm working on a Nopcommerce, and need to generate Invoice (custom made not as what they already provide, because it just doesn't solve our purpose). We need to generate Invoice
in new tab(using another cshtml file) using Controller's method also I'm passing model data on view.
<tr>
<td class="adminTitle">
#Html.NopLabelFor(model => model.ProbableDeliveryDate):
</td>
<td class="adminData">
#Html.EditorFor(model=>model.ProbableDeliveryDate)
</td>
</tr>
<tr>
<td>
#if(Model.CanGenrateInvoice)
{
<input type="submit" name="generateinvoice" value="#T("Admin.Orders.Fields.generateinvoice")" id="generateinvoice" class="adminButton" />
}
</td>
</tr>
I've to post data to get value of probableDeliveryDate to controller method and after that want to open view in new tab.
How can i do this?

If you are getting to the action from the first page via an Html.ActionLink you can do this:
Html.ActionLink("Open Invoice", "ActionName","ControllerName", new { id = Model.InvoiceID }, new { target = "_blank" });
Specifying target = "_blank" will open in the new tab
Update
Since you are posting the model to the controller (I was hoping RedirectToAction could help open a new window/tab but that doesn't look to be the case)
My spidy sense is tingling on the flow you have tho... This is just me but I would do something a little different.. such as
Post the model to the controller
Save the data that generates the invoice
Return the InvoiceID to the action
Add the InvoiceID to the model
Send the model back to the view
Inform the user that
the invoice was generated and show a link - like above - that allows the user to open the invoice OR
this provides the perfect clean solution to show model errors if there were any
Your view could have a piece of razor code that did that:
#{
if(Model.InvoiceID != null && Model.InvoiceID !=0) {
#Html.ActionLink("Open Invoice", "ActionName","ControllerName", new { id = Model.InvoiceID }, new { target = "_blank" });
}
}

Related

ASP.NET Core MVC - VIew is not updated correctly - Ajax?

I have an ASP.NET Core 6 MVC application.
On one page I have a table; I want to support drag'n'drop for its rows. Afterwards the User is able to click on "Submit" and make the changes permanent.
The changes are sent to the controller and persisted to the database, however when I redirect to the GET to show the page again, a part of it is wrong!
#model MyViewModel
<form>
#Html.HiddenFor(y=>y.Id)
<table id="orderTable" class="table">
<thead>
<tr>
<th>
Name
</th>
<th>
Order
</th>
</tr>
</thead>
<tbody>
#foreach (var data in Model.Data)
{
<tr id='#data.Id'>
<td>#data.Name</td>
<td>#data.Order</td>
</tr>
}
</tbody>
</table>
<div class="form-group">
<input type="submit" value="Save" id="SaveOrderButton" />
</div>
</form>
<script>
$(document).ready(function() {
$('#orderTable tbody').sortable();
$("#SaveOrderButton").click(function(e) {
e.preventDefault();
var newOrder = $('#orderTable tbody').sortable('toArray');
$.ajax({
url: '/Controller/Update',
type: 'POST',
data: { rowOrder: newOrder, id: #Html.Raw(Model.Id) },
success: function(response) {
console.log(response);
},
error: function(xhr,status, error){
console.log("An error occurred: " + xhr.responseText);
}
});
});
});
</script>
Backend:
[HttpGet]
public async Task<IActionResult> Order(int id)
{
var data= await context.Data
.AsNoTracking()
.Where(x => x.Id== id)
.ToListAsync();
data = data.OrderByDescending(y => y.Order.HasValue)
.ThenBy(y => y.Order)
.ToList();
var viewModel = new MyViewModel()
{
Data = data,
Id = id,
};
ModelState.Clear(); // found on SO, but does not change anything
return View(viewModel);
}
[HttpPost]
public async Task<IActionResult> Update(int[] rowOrder, int id)
{
var data= await context.Data
.Where(y => rowOrder.Contains(y.Id))
.ToListAsync();
for (int i = 0; i < rowOrder.Count(); i++)
{
data.First(y => y.Id == rowOrder[i]).Order = i;
}
try
{
context.UpdateRange(data);
await context.SaveChangesAsync();
}
catch (Exception ex)
{
logger.LogError("..........");
return Json(500, "Could not update new order.");
}
return RedirectToAction(nameof(Controller.Order), new { id= id});
}
Okay, so I go the the view with GET and everything is shown correctly, then I change something and click on "Save". Everything in the POST will be correctly done. The database is updated.
I then redirect to the GET method again, there everything is loaded correctly from the database and in the correct order.
Then I set a breakpoint in the View and there the stuff in the for is correct too.
However, when I look in the browser, the "Order" column is wrong. The table still shows the data how it looked like after I reordered it and before I clicked on "Save".
What is happening here? Is the sortable lib using a cache in the background that I have to invalidate?
I don't use a cache anywhere in my project, btw.
Also, when I go to the console after a POST, the whole website's HTML is in there.
When I now reload the page with the GET, everything is shown how it is supposed to be.
Has it something to do with Ajax? I have already removed the success and error events, which doesn't change anything.
Has it something to do with Ajax? I have already removed the success
and error events, which doesn't change anything.
Yes, the issue relates the Ajax method.
As we all known, when we use Ajax to update the part of view page, after calling the action method, it will return the response result to the success function, then in the success function, we get the updated data from the response, and then dynamic populate the table to update the page and achieve the part of page refresh behaviors.
So, in your scenario, you can try to use the following methods to display the updated data.
Method 1:
In the Update Action method, return the updated data as result, instead of redirect to another action result. Then, in the Ajax success function, get the data from response, then clear the table content first and re-populate it using the response data.
Method 2:
In the Ajax success function, use location.reload(); method to reload current page, or use window.location.href to refresh the current page.

How can i solve my this issue in MVC grid Delete Controller

Controller:
public ActionResult Delete(int id)
{
Student _std = new Student();
var abc = _dbcon.StudentList.Where(c => c.Roll_ID.Equals(id)).SingleOrDefault();
_dbcon.StudentList.Remove(abc);
_dbcon.SaveChanges();
return View("Test");
}
This is my view and the error comes at foreach loop
View:
#foreach (StudentViewModel _EachStd in #Model.StudentList)
{
<tr>
<td> #_EachStd.Roll_ID</td>
<td> #_EachStd.Name</td>
<td> #_EachStd.Maths</td>
<td> #_EachStd.Urdu</td>
<td> #_EachStd.English</td>
<td>#_EachStd.ObtainNumber</td>
<td>#_EachStd.Percentage</td>
<td> #_EachStd.Grade</td>
<td>#Html.ActionLink("Edit", "Edit", "Home", new {id= #_EachStd.Roll_ID },null)</td>
<td>#Html.ActionLink("Delete", "Delete", "Home", new { id = #_EachStd.Roll_ID }, null)</td>
</tr>
}
</tbody>
</table>
I got Null Error exception, but after refresh i got the record delete. But why the error occur I dont get It.Whenever i run this code my Edit controller is working correctly but my Delete controller is not working correctly, and error is occur like there is "Null erroe exception"
error is occur like there is "Null erroe exception"
You mean a NullReferenceException? That would mean something is null that you're trying to use as though it has a value.
This is my view and the error comes at foreach loop
So then something on this line is null?:
#foreach (StudentViewModel _EachStd in #Model.StudentList)
The only thing you're trying to dereference on that line is Model. So it follows that Model is null. Are you passing a model to your view?
return View("Test");
No, you are not. You need to pass a model to your view in order to use that model within your view.
As an aside, returning a view from this delete operation probably isn't the way to go in the first place. Consider that the user would now be on the URL /Home/Delete and viewing it as a page. This would quickly get confusing for both the user and your code.
Instead of returning a view, especially one without a model, redirect the user to the action which builds the model and displays the view. Which in your code could be something as simple as:
return RedirectToAction("Test");

Html.BeginForm and Kendo Ui in MVC 4

So what I have is a form created with the beginform extension like this
using (Html.BeginForm("SendEmail", "Email", FormMethod.Post, new { id = "emailForm",
onsubmit = "return Check();"})){
inside I created some Kendo Ui widget like this
<table>
<tr>
<td>#Html.LabelFor(x => x.Senders)</td>
<td>
#(Html.Kendo().DropDownList()
.Name("Sender")
.DataTextField("Text")
.DataValueField("Value")
.BindTo(Model.Senders))
</td>
</tr>
<tr>
<td>#Html.Raw(Server.HtmlDecode(#Model.RecipientTable))</td>
</tr>
<tr>
<td colspan ="2">
#(Html.Kendo().MultiSelect()
.Name("Users")
.DataTextField("Name")
.DataValueField("Id")
.Placeholder("Optional - Choose additional users to send emails to:")
.ItemTemplate("#=LastName #, #=FirstName # #=MiddleInitial #")
.TagTemplate("#=LastName #, #=FirstName # #=MiddleInitial #")
.BindTo(Model.OptionalUsers))
</td>
</tr>
in my controller Email I have this method
[HttpPost]
public bool SendEmail(EmailModel Email){ .. stuff....}
Where the EmailModel is tightly bind to the view that contains the form from above. The question and trouble I am having is that is it possible and if so how, to have the model passed to the method containing information about what the user chose? Or is it that I can not use the form's submit and will have to manually get the value and pass it as a JSON to the controller via custom function that does a ajax call?
I thought I read that you weren't using post. The only items that are returned automatically through the post are fields that have been put in a for helper. What we do is
#Html.DropDownListFor(x => x.Sender, new { #class = "ddlSender" })
then in the script we initialize the kendo part of it
$('.ddlSender').kendoDropDownList();
this way the model item is put in a for helper so it gets posted back to the controller and you get the benefits of the kendo dropdown. Hope this helps

Partial view in MVC3 Razor view Engine

I have an view in MVC3 Razor view engine like following image. Now i want to Confirm Connection Action Output show under this link text not New page. How can i done this work?
Please explain with example code.
My View Like this :
#model ESimSol.BusinessObjects.COA_ChartsOfAccount
#{
ViewBag.Title = "Dynamic Account Head Configure";
}
<h2>Dynamic Account Head Configure</h2>
<table border="0">
<tr>
<td> Select an Server Connection </td>
<td style="width:5px">:</td>
<td>#Html.DropDownListFor(m => m.DBConnections, Model.DBConnections.Select(x => new SelectListItem() { Text = x.ConnectionName, Value = x.DBConnectionID.ToString()}))</td>
</tr>
<tr>
<td> </td>
<td style="width:5px"></td>
<td>#Html.ActionLink("Confirm Connection", "ConformConnection")</td>
</tr>
</table>
AND My Controller action Like following :
public ActionResult ConfirmConnection()
{
return PartialView();
}
I'm a big fan of using jquery and ajax for this kind of thing ...
http://api.jquery.com/jQuery.ajax/
If you are following the typical MVC model then you can add an action link to the page using something like ...
#Html.ActionLink("controller", "action", args);
but I would go for the ajax driven approach ...
<script type="text/javascript">
var ajaxBaseUrl = '#Url.Action("yourController", "ConformConnection", new { args })';
$(link).click(function () {
var currentElement = $(this);
$.ajax({
url: ajaxBaseUrl,
data: { any other queryString stuff u want to pass },
type: 'POST',
success: function (data) {
// action to take when the ajax call comes back
}
});
});
});
</script>
First move your markup to a partial view. After that define an action method that renders your partial view.
[ChildActionOnly]
public ActionResult ConfirmConnection(COA_ChartsOfAccount model)
{
return PartialView("MyPartialView", model);
}
ChildActionOnly attribute makes sure this action method cannot be called by a HTTP request.
Then you can display it whenever you want using Html.Action method.
#Html.Action("ConfirmConnection", "MyController", new { model = Model })
Ignore passing the model as a parameter if it doesn't change by the page you display it. You can retrieve it in your action method.

Can't set SelectedItem in DropDownList in my MVC3 view

I know that I can set the SelectedItem in my controller, but I can't figure out how to set it in my view. I'm working on a sort of flashcard (study guide) application and I have imported about 400 test questions. Now I want to write a page for the instructor to be able to select a "Category" for each question. I'd like them to be able to update the category for all the questions on one page. My model has a question entity that contains a foreign key field to the category entity (the field is called QuestionCategory). So, my view is based on the Question entity, but I'm sending over the list of Categories (there are 14) in the ViewBag (so I don't have to send a full SelectList over with each of the 400 questions. As my view is iterating thru the items in my View, I just want to add a SelectList that contains the 14 categories in my ViewBag and then set the SelectedItem based on the value of item.QuestionCategory. I can't make it work.
Here's my controller action:
public ActionResult Index()
{
var context = new HBModel.HBEntities();
var query = from q in context.tblQuestions.Include("tblCategory") select q;
var questions = query.ToList();
ViewBag.Categories = new SelectList(context.tblCategories, "CategoryID", "CategoryName");
return View(questions);
}
Here's some of the things I've tried in the view (with associated error messages in the comments)
#model IEnumerable<HBModel.tblQuestion>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
Question
</th>
<th>
Answer
</th>
<th>
AnswerSource
</th>
<th>
Category
</th>
<th>
Action
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#item.Question
</td>
<td>
#item.Answer
</td>
<td>
#item.AnswerSource
</td>
<td>
#item.tblCategory.CategoryName
#*This one works, but cannot initialize the selected item to be current database value*#
#Html.DropDownList("Categories")
#*compile error - CS0200: Property or indexer 'System.Web.Mvc.SelectList.SelectedValue' cannot be assigned to -- it is read only*#
#*#Html.DropDownListFor(m => item.QuestionCategory, (ViewBag.Categories as SelectList).SelectedValue = item.QuestionCategory)*#
#*error {"DataBinding: 'System.Web.Mvc.SelectListItem' does not contain a property with the name 'CategoryId'."}*#
#Html.DropDownListFor(m => item.QuestionCategory, new SelectList(ViewBag.Categories, "CategoryId", "CategoryName"))
#*error - {"DataBinding: 'System.Char' does not contain a property with the name 'CategoryId'."}*#
#Html.DropDownListFor(m => item.QuestionCategory, new SelectList("Categories", "CategoryId", "CategoryName"))
)
</td>
<td style="width: 100px">
#Html.ActionLink("Edit", "Edit", new { id = item.QuestionID }) |
#Html.ActionLink("Delete", "Delete", new { id = item.QuestionID })
</td>
</tr>
}
</table>
Of course, if I can get this to work, I'll need to try and add an action to go back to the controller and update all the records, but I'll just be happy to resolve my current issue.
I would really appreciate any help on this - Thanks!
You need to explicitly create the options in the select tag, using #Html.DropDownList, as follows (taken from a working app):
#Html.DropDownListFor(model => model.IdAccountFrom, ((IEnumerable<FlatAdmin.Domain.Entities.Account>)ViewBag.AllAccounts).Select(option => new SelectListItem {
Text = (option == null ? "None" : option.AccountName),
Value = option.AccountId.ToString(),
Selected = (Model != null) && (option.AccountId == Model.IdAccountFrom)
}), "Choose...")
#Html.ValidationMessageFor(model => model.IdAccountFrom)
You obviously need to change to the properties on your #Model.
NOTE:
This code was auto-generated by the MvcScaffolding NuGet package when I scaffolded a controller.
This package requires you to use Entity Framework Code First POCO classes for your entities. These are easy to generate from an existing database using the Entity Framework Power Tools CTP.
With MVC, you need to spend some time researching the tooling that is out there to help you generate the stuff that you need. Using these tools is a great way to get started and to see how to do things. You can then tweak the output to your heart's content.

Resources