Data is not binding to Kendo dropdown list list is returning form my method
My dropdown
#(Html.Kendo().DropDownListFor(model => model.ParentAssetID)
.OptionLabel(" ")
.Name("ParentAssetID")
.DataTextField("AssetName")
.DataValueField("AssetId")
.SelectedIndex(0)
.Text(string.Empty)
.DataSource(source =>
{
source.Read(read =>
{
read.Url("../Asset/GetAllAssetsByCompanyId");
});
}))
my Action Result
public IEnumerable<AssetDetails> GetAllAssetsByCompanyId()
{
IList<AssetDetails> _assetSearchlist;
using (var client = new HttpClient())
{
AssetRepository assetrep = new AssetRepository();
Guid cp = new Guid(Session["CurrentCompanyId"].ToString());
_assetSearchlist = assetrep.GetAllAssetsByCompanyId(cp, "", "", "");
return _assetSearchlist;
}
}
public JsonResult GetOpportunityListByAccount(string Id)
{
Guid ID = new Guid(Id);
List<OpportunityViewModel> cpvm = new List<OpportunityViewModel>();
List<CrmOpportunity> crmOppList = new List<CrmOpportunity>();
cpvm = srv.OpportunitySet.Where(z => z.CustomerId.Id == ID).ToList();
foreach (var crm in cpvm )
{
CrmOpportunity crmOpp = new CrmOpportunity();
crmOpp.Id = crm.Id;
crmOpp.Name = crm.Name;
crmOppList.Add(crmOpp);
}
return Json(crmOppList, JsonRequestBehavior.AllowGet);
}
#(Html.Kendo().DropDownListFor(x => x.FromOpportunity)
.Name("OpportunityDDL")
.DataTextField("Name")
.DataValueField("Id")
.DataSource(source => {
source.Read(read =>
{
read.Action("GetOpportunityListByAccount", "CrmIntegration");
})
. ServerFiltering(true);
})
.HtmlAttributes( new { style = "margin-left:13px; width: 275px;" })
)
Data access is a little truncated but this is what you'll need to do
#(Html.Kendo().DropDownListFor(model => model.ParentAssetID)
.OptionLabel(" ")
.Name("ParentAssetID")
.DataTextField("AssetName")
.DataValueField("AssetId")
.SelectedIndex(0)
.Text(string.Empty)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetAllAssetsByCompanyId", "Asset");
});
}))
Only a minor change but have you tried read.Action? Also is maybe try removing the following;
DropDownListFor(model => model.ParentAssetID)
and replace with
DropDownListFor<ClassName>()
Only a thought.
Related
I have been looking around the Telerik forums & Stackoverflow for an answer for this and I am completely stuck and unable to figure out the issue.
I am using the Kendo UI for Asp.Net Core Scheduler Control. I have it reading the data from my controller fine. However, I cannot get it call the HttpPut handler correctly.
When checking the traffic I get the following response, and therefor my breakpoint inside my HttpPut handler will never be hit.
400 - Bad Request
{"":["The input was not valid."]}
My code in my view is:
#(Html.Kendo().Scheduler<MeetingViewModel>()
.Name("SchedulerView")
.Height(500)
.Date(DateTime.Now.ToUniversalTime())
.StartTime(new DateTime(2018, 11, 28, 0, 00, 00).ToUniversalTime())
.MajorTick(30)
.ShowWorkHours(false)
.Footer(false)
.Editable(edit =>
{
//edit.Resize(false);
edit.Create(false);
})
.Views(views =>
{
views.TimelineView(timeline => timeline.EventHeight(50));
//views.TimelineWeekView(timeline => timeline.EventHeight(50));
//views.TimelineWorkWeekView(timeline => timeline.EventHeight(50));
//views.TimelineMonthView(timeline =>
//{
// timeline.StartTime(DateTime.Now);
// timeline.EndTime(DateTime.Now.AddMonths(1));
// timeline.MajorTick(1440);
// timeline.EventHeight(50);
//});
})
.Timezone("Etc/UTC")
.Group(group => group.Resources("WorkCenters" /*,"Attendees"*/).Orientation(SchedulerGroupOrientation.Vertical))
.Resources(resource =>
{
resource.Add(m => m.ScheduleRowID)
.Title("Work Center")
.Name("WorkCenters")
.DataTextField("Text")
.DataValueField("Value")
.DataColorField("Color")
.BindTo(#Model.AvailableWorkCenters);
})
.DataSource(d => d
.ServerOperation(true)
.WebApi()
.Model(m =>
{
m.Id(f => f.ActivityID);
m.Field(f => f.Title).DefaultValue("No title");
//m.RecurrenceId(f => f.RecurrenceID);
m.Field(f => f.Description).DefaultValue("No Description");
})
.Events(events => events.Error("error_handler"))
.Read(read => read.Action("GetActivities", "Scheduler").Data("setRequestDateTimes"))
//.Create(create => create.Action("Post", "Scheduler"))
.Update(update => update.Action("PutActivity", "Scheduler", new { id = "{0}" }).Type(HttpVerbs.Put))
//.Destroy(destroy => destroy.Action("Delete", "Scheduler", new { id = "{0}" }))
)))
And my API Controller is as follows:
[Route("Api/[controller]")]
[ApiController]
public class SchedulerController : DawnController
{
public SchedulerController(DatabaseContext context) : base(context)
{
}
[HttpGet]
public DataSourceResult GetActivities([DataSourceRequest] DataSourceRequest request, DateTime requestStartDateTime, DateTime requestEndDateTime)
{
//Kendo doesnt seem to send the full date range. so + 1 day to end
requestEndDateTime = requestEndDateTime.AddDays(1);
List<MeetingViewModel> test = new List<MeetingViewModel>();
foreach (JobTask jobTask in Context.JobTask)
{
if (JobTask.HasActivityInDateRange(jobTask, requestStartDateTime, requestEndDateTime))
{
foreach (Activites jobTaskAct in jobTask.Activites)
{
test.Add(new MeetingViewModel()
{
JobTaskID = jobTask.JobTaskId,
ActivityID = jobTaskAct.ActivityId,
Title = jobTaskAct.Name,
Description = jobTaskAct.Description,
Start = jobTaskAct.StartTime.ToUniversalTime(),
End = jobTaskAct.EndTime.ToUniversalTime(),
IsAllDay = false,
ScheduleRowID = jobTaskAct.Workcenter.WorkCenterId,
});
}
}
}
return test.ToDataSourceResult(request);
}
[HttpPut("{id}")]
public IActionResult PutActivity(int id, MeetingViewModel task)
{
if (ModelState.IsValid && id == task.ActivityID)
{
try
{
//breakpoint here
bool a = true;
//update the db here
}
catch (DbUpdateConcurrencyException)
{
return new NotFoundResult();
}
return new StatusCodeResult(200);
}
else
{
return BadRequest(ModelState.Values.SelectMany(v => v.Errors).Select(error => error.ErrorMessage));
}
}
}
Thanks
The URL exposing your controller method PutActivity in your controller example is PUT api/scheduler/{id}
To access that URL use this Update method.
.Update(update => update.Action("Put", "Scheduler", new { id = "{0}" }))
See this demo as example
Alternatively
If you want to implment the URL api/Scheduler/PutActivity/{id} (similar pattern to your GET) then you will need to modify the attribute over the put method as follows.
[HttpPut("PutActivity/{id}")]
public IActionResult PutActivity(int id, MeetingViewModel task)
Then you can call api/Scheduler/PutActivity/{id} with this asp.net action call.
.Update(update => update.Action("PutActivity", "Scheduler", new { id = "{0}" }).Type(HttpVerbs.Put))
I am working on yii2. I have came across a point in which I have to send an email to a person when a meter is installed and it's images are uploaded to the server. Fro this I have already configured the swift mailer.
There is a model named Installations which have a function which saves all the installation data.
public static function saveAll($inputs){
$coutner = 0;
$arr_status = [];
foreach ($inputs as $input) {
$s = new Installations;
foreach ((array)$input as $key => $value) {
if($key != 'image_names') {
if ($s->hasAttribute($key)) {
$s->$key = $value;
}
}
}
$user = Yii::$app->user;
if (isset($input->auth_key) && Users::find()->where(['auth_key' => $input->auth_key])->exists()) {
$user = Users::find()->where(['auth_key' => $input->auth_key])->one();
}
$s->created_by = $user->id;
if (Installations::find()->where(['ref_no' => $input->ref_no])->exists()) {
$arr_status[] = ['install_id' => $input->install_id, 'status' => 2, 'messages' => "Ref # Already exists"];
continue;
}
$s->sync_date = date('Y-m-d H:i:sāā');
if($s->save()){
if ($s->istallation_status == 'Installed') {
Meters::change_status_byinstall($s->meter_msn, Meters::$status_titles[4]);
}
else if ($s->istallation_status != 'Installed' && $s->comm_status =='Failed')
{
Meters::change_status_byinstall($s->meter_msn, Meters::$status_titles[5]);
}
$arr_status[] = ['install_id' => $input->install_id, 'status' => 1];
$coutner++;
if (isset($input->doc_images_name)) {
foreach ($input->doc_images_name as $img) {
$image = new InstallationImages;
$image->image_name = $img->image_name;
$image->installation_id = $s->id;
$image->save();
}
}
if (isset($input->site_images_name)) {
foreach ($input->site_images_name as $img2) {
$image2 = new InstallationImagesSite;
$image2->image_name = $img2->image_name;
$image2->installation_id = $s->id;
$image2->save();
}
}
}else{
$arr_status[] = ['install_id' => $input->install_id, 'status' => 0, 'messages' => $s->errors];
}
$status = $s->istallation_status;
$msn = $s->meter_msn;
$com = $s->comm_status;
// want to pass these variables to the controller function
}
return ['status' => 'OK', 'details' => $arr_status, 'records_saved' => $coutner];
}
Now There Is a Controller name InstallationController. This controller contains all the APIs for my mobile application. Below are two main functions in it
public function actionAddnew()
{
$fp = fopen('debugeeeeeee.txt', 'w+');
fwrite($fp, file_get_contents('php://input'));
fclose($fp);
$inputs = json_decode(file_get_contents('php://input'));
return Installations::saveAll($inputs);
}
public function actionSavephoto()
{
try {
$count = 0;
foreach ($_FILES as $f) {
$dd = pathinfo($f['name']);
if (!isset($dd['extension']) || !in_array($dd['extension'], array('jpg', 'png', 'gif'))) {
return ['status' => 'ERROR', 'uploaded_files' => $count, 'message' => 'Invalid File'];
break;
}
if (move_uploaded_file($f['tmp_name'], Installations::UPLOAD_FOLDER . $f['name'])) {
$count++;
return ['status' => 'OK', 'uploaded_files' => $count];
break;
} else {
return ['status' => 'ERROR', 'uploaded_files' => $count];
break;
}
}
} catch (Exception $x) {
return ['status' => 'ERROR', 'message' => $x->getMessage()];
}
}
The mobile application will call the Addnew() api and after that it will call the savephoto. Now I want to pass $msn,$status and $com values from the Model to the controller function Savephoto.
For this I have tried to use session variables but still I am unable to get by desired result(s).
I have also checked the question Yii, how to pass variables to model from controller?
but it didn't worked for me.
How can I achieve it?
Any help would be highly appreciated.
The only way to get those values out of saveAll() is to return them. Presently, they are defined on an object in $s that is overwritten each loop. The best way to do that seems to be creating an array outside of your foreach ($inputs... loop and appending each created Installations object.
Return that at the end, and pass it (or just the relevant element from it) into actionSavephoto() as a parameter. Then, those values will be accessible of properties of that passed object. This handling will occur in the code that is not pictured which calls actionAddNew() and then actionSavephoto()
NEST doesn't appear to support the pattern replace char filter described here:
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/analysis-pattern-replace-charfilter.html
I've created an issue at https://github.com/elasticsearch/elasticsearch-net/issues/543.
Most of my indexing is working so I would like to continue to use NEST. Is there a way I can work around this using some manual json injection at some point during the index configuration? I'm new to NEST so not sure if this is doable.
Specifically I'm hoping to use the pattern replace char filter to remove unit numbers from a street address before they are run through a custom analyzer (i.e. #205 - 1260 Broadway becomes 1260 Broadway). Because of the custom analyzer, I believe I need to use this char filter to accomplish this.
My current configuration looks like this:
elasticClient.CreateIndex("geocoding", c => c
.Analysis(ad => ad
.Analyzers(ab => ab
.Add("address-index", new CustomAnalyzer()
{
Tokenizer = "whitespace",
Filter = new List<string>() { "lowercase", "synonym" }
})
.Add("address-search", new CustomAnalyzer()
{
Tokenizer = "whitespace",
Filter = new List<string>() { "lowercase" },
CharFilter = new List<string>() { "drop-unit" }
})
)
.CharFilters(cfb => cfb
.Add("drop-unit", new CharFilter()) //missing char filter here
)
.TokenFilters(tfb => tfb
.Add("synonym", new SynonymTokenFilter()
{
Expand = true,
SynonymsPath = "analysis/synonym.txt"
})
)
)
UPDATE:
As of May 2014, NEST now supports the pattern replace char filter: https://github.com/elasticsearch/elasticsearch-net/pull/637
Instead of using the fluent settings during your index creation you can use the Settings.Add approach to add to the FluentDictionary in a more manual way, but with complete control over what settings are passed in. An example of this is shown in Create Index of the NEST Documentation. I am using this approach for a very similar reason.
You configuration would look something similar to the following:
elasticClient.CreateIndex("geocoding", c => c.
.Settings(s => s.
.Add("analysis.analyzer.address-index.type", "custom")
.Add("analysis.analyzer.address-index.tokenizer", "whitespace")
.Add("analysis.analyzer.address-index.filter.0", "lowercase")
.Add("analysis.analyzer.address-index.filter.1", "synonym")
.Add("anaylsis.analyzer.address-search.type", "custom")
.Add("analysis.analyzer.address-search.tokenizer", "whitespace")
.Add("analysis.analyzer.address-search.filter.0", "lowercase")
.Add("analysis.analyzer.address-search.char_filter.0", "drop-unit")
.Add("analysis.char_filter.drop-unit.type", "mapping")
.Add("analysis.char_filter.drop-unit.mappings.0", "<mapping1>")
.Add("analysis.char_filter.drop-unit.mappings.1", "<mapping2>")
...
)
);
You will need to replace <mapping1> and <mapping2> above with your actual char_filter mappings that you want to use. Please note that I have not used a char_filter before, so the settings values may be a little off, but should get you going in the right direction.
Just to provide a follow-up to Paige's very helpful answer, it looks like you can combine the fluent and manual Settings.Add approaches. The following worked for me:
elasticClient.CreateIndex("geocoding", c => c
.Settings(s => s
.Add("analysis.char_filter.drop_unit.type", "pattern_replace")
.Add("analysis.char_filter.drop_unit.pattern", #"#\d+\s-\s")
.Add("analysis.char_filter.drop_unit.replacement", "")
)
.Analysis(ad => ad
.Analyzers(ab => ab
.Add("address_index", new CustomAnalyzer()
{
Tokenizer = "whitespace",
Filter = new List<string>() { "lowercase", "synonym" }
})
.Add("address_search", new CustomAnalyzer()
{
CharFilter = new List<string> { "drop_unit" },
Tokenizer = "whitespace",
Filter = new List<string>() { "lowercase" }
})
)
.TokenFilters(tfb => tfb
.Add("synonym", new SynonymTokenFilter()
{
Expand = true,
SynonymsPath = "analysis/synonym.txt"
})
)
)
EsClient.CreateIndex("universal_de", c => c
.NumberOfReplicas(1)
.NumberOfShards(5)
.Settings(s => s //just as an example
.Add("merge.policy.merge_factor", "10")
.Add("search.slowlog.threshold.fetch.warn", "1s")
.Add("analysis.char_filter.drop_chars.type", "pattern_replace")
.Add("analysis.char_filter.drop_chars.pattern", #"[^0-9]")
.Add("analysis.char_filter.drop_chars.replacement", "")
.Add("analysis.char_filter.drop_specChars.type", "pattern_replace")
.Add("analysis.char_filter.drop_specChars.pattern", #"[^0-9a-zA-Z]")
.Add("analysis.char_filter.drop_specChars.replacement", "")
)
.Analysis(descriptor => descriptor
.Analyzers(bases => bases
.Add("folded_word", new CustomAnalyzer()
{
Filter = new List<string> { "lowercase", "asciifolding", "trim" },
Tokenizer = "standard"
}
)
.Add("trimmed_number", new CustomAnalyzer()
{
CharFilter = new List<string> { "drop_chars" },
Tokenizer = "standard",
Filter = new List<string>() { "lowercase" }
})
.Add("trimmed_specChars", new CustomAnalyzer()
{
CharFilter = new List<string> { "drop_specChars" },
Tokenizer = "standard",
Filter = new List<string>() { "lowercase" }
})
)
)
.AddMapping<Business>(m => m
//.MapFromAttributes()
.Properties(props => props
.MultiField(mf => mf
.Name(t => t.DirectoryName)
.Fields(fs => fs
.String(s => s.Name(t => t.DirectoryName).Analyzer("standard"))
.String(s => s.Name(t => t.DirectoryName.Suffix("folded")).Analyzer("folded_word"))
)
)
.MultiField(mf => mf
.Name(t => t.Phone)
.Fields(fs => fs
.String(s => s.Name(t => t.Phone).Analyzer("trimmed_number"))
)
)
This is how you create the index and add the mapping.
Now to search i have something like this :
var result = _Instance.Search<Business>(q => q
.TrackScores(true)
.Query(qq =>
{
QueryContainer termQuery = null;
if (!string.IsNullOrWhiteSpace(input.searchTerm))
{
var toLowSearchTerm = input.searchTerm.ToLower();
termQuery |= qq.QueryString(qs => qs
.OnFieldsWithBoost(f => f
.Add("directoryName.folded", 5.0)
)
.Query(toLowSearchTerm));
termQuery |= qq.Fuzzy(fz => fz.OnField("directoryName.folded").Value(toLowSearchTerm).MaxExpansions(2));
termQuery |= qq.Term("phone", Regex.Replace(toLowSearchTerm, #"[^0-9]", ""));
}
return termQuery;
})
.Skip(input.skip)
.Take(input.take)
);
NEW: I managed to use the pattern replace in a better way like this :
.Analysis(descriptor => descriptor
.Analyzers(bases => bases
.Add("folded_word", new CustomAnalyzer()
{
Filter = new List<string> { "lowercase", "asciifolding", "trim" },
Tokenizer = "standard"
}
)
.Add("trimmed_number", new CustomAnalyzer()
{
CharFilter = new List<string> { "drop_chars" },
Tokenizer = "standard",
Filter = new List<string>() { "lowercase" }
})
.Add("trimmed_specChars", new CustomAnalyzer()
{
CharFilter = new List<string> { "drop_specChars" },
Tokenizer = "standard",
Filter = new List<string>() { "lowercase" }
})
.Add("autocomplete", new CustomAnalyzer()
{
Tokenizer = new WhitespaceTokenizer().Type,
Filter = new List<string>() { "lowercase", "asciifolding", "trim", "engram" }
}
)
)
.TokenFilters(i => i
.Add("engram", new EdgeNGramTokenFilter
{
MinGram = 3,
MaxGram = 15
}
)
)
.CharFilters(cf => cf
.Add("drop_chars", new PatternReplaceCharFilter
{
Pattern = #"[^0-9]",
Replacement = ""
}
)
.Add("drop_specChars", new PatternReplaceCharFilter
{
Pattern = #"[^0-9a-zA-Z]",
Replacement = ""
}
)
)
)
i'm using kendo ui in my asp.net mvc 4 with razor views and encounter problem with kendo combo when the list load from an action via ajax with sending parameters to the server like the sample here:HERE
becuase the table has more then 2,000 rows.
when i load the edit page, the combo load and filter the data as expected, but the value of this field is - [object object].
i did declare the .DataTextField("ProffName") + .DataValueField("ID")
My ClientsController:
public ActionResult Edit(int id = 0)
{
Clients clients = db.Clients.Find(id);
if (clients == null)
{
return HttpNotFound();
}
ViewData["MyAgency"] = new SelectList(db.Agency, "ID", "AgentName", clients.AgencyId);
ViewData["MyCategory1"] = new SelectList(db.CategoryTbl, "ID", "category", clients.CategoryId);
List<SelectListItem> obj = new List<SelectListItem>();
obj.Add(new SelectListItem { Text = "male", Value = "1" });
obj.Add(new SelectListItem { Text = "female", Value = "2" });
obj.Add(new SelectListItem { Text = "choose", Value = "0" });
ViewData["MyMin"] = obj;
ViewBag.ProffID = new SelectList(db.ProfTBL, "ID", "ProffName", clients.ProffID);
ViewBag.Metapel = new SelectList(db.Workers, "ID", "WorkerName", clients.Metapel);
return View(clients);
}
My ProffController:
public ActionResult ProffVM_Read(string text)
{
var Proff_Tbl = db.ProfTBL.Select(proff => new ProffVm { ID = proff.ID, ProffName = proff.ProffName });
if (!string.IsNullOrEmpty(text))
{
Proff_Tbl = Proff_Tbl.Where(p => p.ProffName.Contains(text));
}
return Json(Proff_Tbl, JsonRequestBehavior.AllowGet);
}
and the Kendo combo:
#Html.Label("Proff")
#(Html.Kendo().ComboBoxFor(model => model.ProffID)
.Name("proffCbo")
.DataTextField("ProffName")
.DataValueField("ID")
.Events(e => e
.Select("proffCbo_select")
.Change("proffCbo_change")
)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("ProffVM_Read", "Proff")
.Data("onAdditionalData");
});
})
)
where am i wrong ???
i can change this combo to textbox but... i have to realize the magic.
Thanks
Change these two lines
var Proff_Tbl = db.ProfTBL.Select(proff => new ProffVm { ID = proff.ID, ProffName = proff.ProffName });
Proff_Tbl = Proff_Tbl.Where(p => p.ProffName.Contains(text));
to
var Proff_Tbl = db.ProfTBL.Select(proff => new ProffVm { ID = proff.ID, ProffName = proff.ProffName }).ToList();
Proff_Tbl = Proff_Tbl.Where(p => p.ProffName.Contains(text)).ToList();
I am doing Export to csv functionality in my MVC project. Currently if i write code on each page it works properly. but i want to avoid duplication of code doing export functionality centrally.
Here is my controller code
public ActionResult Export(string filterBy)
{
GridState gs = new GridState();
gs.Filter = filterBy;
gs.Page = 1;
gs.Size = int.MaxValue;
IEnumerable cities = City.GetAll().AsEnumerable().AsQueryable().ToGridModel(gs).Data;
MemoryStream output = new MemoryStream();
StreamWriter writer = new StreamWriter(output, Encoding.UTF8);
writer.Write("Country Name,");
writer.Write("State Name,");
writer.Write("City Name,");
writer.Write("City STD Code,");
writer.Write("Is Display");
writer.WriteLine();
foreach (CityViewModel city in cities)
{
writer.Write(city.CountryName);
writer.Write(",");
writer.Write("\"");
writer.Write(city.StateName);
writer.Write("\"");
writer.Write(",");
writer.Write("\"");
writer.Write(city.City.Name);
writer.Write("\"");
writer.Write(",");
writer.Write(city.City.STDCode);
writer.Write("\"");
writer.Write(",");
writer.Write(city.City.IsDisplay);
writer.WriteLine();
}
writer.Flush();
output.Position = 0;
return File(output, "text/comma-separated-values", "city.csv");
}
This is my View:
#model Telerik.Web.Mvc.GridModel<QuexstERP.BusinessCore.BusinessEntities.SysAdmin.CityViewModel>
#using Telerik.Web.Mvc.UI
#{
ViewBag.Title = "City List";
}
#(Html.Telerik().Grid(Model.Data)
.Name("Grid")
.DataKeys(keys => keys.Add(c => c.City.Id))
.ToolBar(commands => commands.Insert().ButtonType(GridButtonType.Image).ImageHtmlAttributes(new { style = "margin-left:0", title = "Add" }))
.ToolBar(commands => commands
.Custom()
.HtmlAttributes(new { id = "TestFilter", onclick = "command_onClick(this)" })
.Text("Export to csv")
.Action("Export", "City", new { filterBy = "~" }))
.DataBinding(dataBinding =>
dataBinding.Server()
.Select("Select", "City", new { GridButtonType.Text })
.Insert("Create", "City", new { GridButtonType.Text })
.Update("Save", "City", new { GridButtonType.Text })
.Delete("Delete", "City", new { GridButtonType.Text }))
.Columns(columns =>
{
columns.Command(commands =>
{
commands.Custom("Edit").Action("Edit", "City").ImageHtmlAttributes(new { #class = "t-edit" }).ButtonType(GridButtonType.Image).HtmlAttributes(new { title = "Edit", #class = "RightAlign" });
}).Width(40).Title("Edit").Visible(OperationHelper.EditOperation);
columns.Command(commands =>
{
commands.Delete().ButtonType(GridButtonType.Image).HtmlAttributes(new { title = "Delete", #class = "RightAlign" });
}).Width(40).Title("Delete").Visible(OperationHelper.DeleteOperation);
columns.Bound(p => p.CountryName).Width(200).Title("Country");
columns.Bound(p => p.StateName).Width(200).Title("State");
columns.Bound(p => p.City.Name).Width(310).Title("City");
columns.Bound(p => p.City.STDCode).Width(200).Title("STD Code");
columns.Bound(p => p.City.IsDisplay).Width(110).Title("IsDisplay");
})
.Pageable()
.Scrollable()
.Sortable()
.Filterable()
.Resizable(command => command.Columns(true))
)
#section HeadContent {
<script type="text/javascript">
function command_onClick(e) {
var grid = $('#Grid').data('tGrid');
var $cmd = $('#TestFilter');
// Get its 'href' attribute - the URL where it would navigate to
var href = $cmd.attr('href');
// Update the 'filter' parameter with the grids' current filtering state
href = href.replace(/filterBy=(.*)/, 'filterBy=' + (grid.filterBy || '~'));
// Update the 'order' parameter with the grids' current ordering state
href = href.replace(/orderBy=([^&]*)/, 'orderBy=' + (grid.orderBy || '~'));
// Update the 'page' parameter with the grids' current page
href = href.replace(/page=([^&]*)/, 'page=' + grid.currentPage);
// Update the 'href' attribute
$cmd.attr('href', href);
}
</script>
}
I want to do Export to CSV centrally. as many of the form like state, country and country in my project have the exporting functionality. is it possible to write one generic class and pass parameter to it. and export to csv is done centrally???
We achieved something similar to this by binding datasources to a GridView within a controller method e.g.
var data = GetSomeData();
var grid = new GridView { DataSource = data };
grid.DataBind();
Response.ClearContent();
Response.AddHeader("content-disposition", "attachment; filename=MyExcel.xls");
Response.ContentType = "application/vnd.ms-excel";
var sw = new StringWriter();
var htw = new HtmlTextWriter(sw);
grid.RenderControl(htw);
Response.Write(sw.ToString());
Response.End();
This way you can just set the relevant datasource on the GridView and return a dump of the grid data in the output stream. With a bit of refactoring we were able to make this generic and it is now used by all of our UI grids for exporting to Excel/CSV.
Just for the reference. Don't bind data to the grid and then export it to excel. It will give you
the file you are trying to open is in a different format than
specified by the file extension
Error when you try to open Excel.
I have done this solution for above problem
public static void ExportToExcel(IEnumerable<dynamic> data, string sheetName)
{
XLWorkbook wb = new XLWorkbook();
var ws = wb.Worksheets.Add(sheetName);
ws.Cell(2, 1).InsertTable(data);
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
HttpContext.Current.Response.AddHeader("content-disposition", String.Format(#"attachment;filename={0}.xlsx",sheetName.Replace(" ","_")));
using (MemoryStream memoryStream = new MemoryStream())
{
wb.SaveAs(memoryStream);
memoryStream.WriteTo(HttpContext.Current.Response.OutputStream);
memoryStream.Close();
}
HttpContext.Current.Response.End();
}
It get data dynamically. use ClosedXml so no error and the Export to Excel functionality is central in application
Hope this will help someone. :)