AutoMapper: "Abaikan sisanya"?


206

Apakah ada cara untuk memberitahu AutoMapper untuk mengabaikan semua properti kecuali yang dipetakan secara eksplisit?

Saya memiliki kelas DTO eksternal yang cenderung berubah dari luar dan saya ingin menghindari menentukan masing-masing properti untuk diabaikan secara eksplisit, karena menambahkan properti baru akan merusak fungsionalitas (menyebabkan pengecualian) ketika mencoba memetakannya ke objek saya sendiri.


1
dengan ValueInjecter valueinjecter.codeplex.com/documentation Anda membuat ValueInjections yang memiliki alghoritma pemetaan dan memetakan antara properti tertentu, dan mereka tidak peduli dengan properti lainnya
Omu

24
Bagi mereka yang menggunakan Automapper> versi 5, lewati untuk melihat jawaban yang merinci.ForAllOtherMembers(opts => opts.Ignore())
Jack Ukleja

@Schneider ".ForAllOtherMembers (opts => opts.Ignore ())" berbeda dengan ekstensi "IgnoreAllNonExisting" di sini, perbedaan utama adalah jika Anda tidak mengkonfigurasi properti secara eksplisit, dengan ".ForAllOtherMembers (opts => opts.Ignore (opts => opts.Ignore) )) "Anda tidak akan mendapatkan apa pun yang dipetakan. gunakan "IgnoreAllNonExisting" tanpa properti konfigurasi secara eksplisit, Anda masih mendapatkan beberapa properti yang dipetakan (properti dengan nama yang sama) dengan nilai.
Naga

Iya. Anggota ForAllOtherMembers adalah jawabannya. Jawaban IgnoreUnmapped tidak melakukan apa pun kecuali menyebabkan config-valid-assert lulus, karena anggota yang belum dipetakan diabaikan.
N73k

Perlu dicatat bahwa ketika melakukan ini, Anda secara eksplisit menyembunyikan kemungkinan perubahan yang relevan atau penting di kelas yang dipetakan. Memiliki pemetaan eksplisit untuk setiap properti akan membuat Anda mengalami tes yang rusak setiap kali kelas yang dipetakan berubah, memaksa Anda untuk mengevaluasinya dengan benar. (Mengingat bahwa Anda memiliki tes melakukan AssertConfigurationIsValid()panggilan) Karena ini, saya menganggap "Abaikan sisanya" sebagai antipattern.
Arve Systad

Jawaban:


83

Ini adalah metode ekstensi yang saya tulis yang mengabaikan semua properti yang tidak ada di tujuan. Tidak yakin apakah masih akan berguna karena pertanyaannya sudah lebih dari dua tahun, tetapi saya mengalami masalah yang sama karena harus menambahkan banyak panggilan Abaikan manual.

public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>
(this IMappingExpression<TSource, TDestination> expression)
{
    var flags = BindingFlags.Public | BindingFlags.Instance;
    var sourceType = typeof (TSource);
    var destinationProperties = typeof (TDestination).GetProperties(flags);

    foreach (var property in destinationProperties)
    {
        if (sourceType.GetProperty(property.Name, flags) == null)
        {
            expression.ForMember(property.Name, opt => opt.Ignore());
        }
    }
    return expression;
}

Pemakaian:

Mapper.CreateMap<SourceType, DestinationType>()
                .IgnoreAllNonExisting();

UPDATE : Rupanya ini tidak berfungsi dengan benar jika Anda memiliki pemetaan khusus karena menimpa mereka. Saya kira itu masih bisa berfungsi jika panggilan IgnoreAllNonExisting dulu dan kemudian pemetaan kustom nanti.

schdr memiliki solusi (sebagai jawaban untuk pertanyaan ini) yang digunakan Mapper.GetAllTypeMaps()untuk mengetahui properti mana yang belum dipetakan dan mengabaikannya secara otomatis. Sepertinya solusi yang lebih kuat bagi saya.


Saya belum pernah menggunakan AutoMapper untuk beberapa waktu, tetapi saya akan menerima jawaban Anda jika itu berfungsi untuk Anda :).
Igor Brejc

2
Terima kasih!! Saya menemukan ini sangat berguna. Mengabaikan properti secara individual mengalahkan tujuan menggunakan automapper dalam situasi saya.
Daniel Robinson

Lihat jawaban berikutnya untuk jawaban yang tidak memiliki masalah timpa
Jason Coyne

3
Metode ini harus pada kode asli autoMapper! Sangat baik terima kasih!
Felipe Oriani

2
FYI, Jimmy sendiri (penulis AutoMapper) berkomentar di bawah ini bahwa jawaban @ nimim benar untuk versi 5+
Worthy7

244

Dari apa yang saya pahami pertanyaannya adalah bahwa ada bidang di tujuan yang tidak memiliki bidang yang dipetakan di sumbernya, itulah sebabnya Anda mencari cara untuk Mengabaikan bidang tujuan yang tidak dipetakan.

Alih-alih menerapkan dan menggunakan metode ekstensi ini, Anda cukup menggunakan

Mapper.CreateMap<sourceModel, destinationModel>(MemberList.Source);  

Sekarang automapper tahu bahwa itu hanya perlu memvalidasi bahwa semua bidang sumber dipetakan tetapi tidak sebaliknya.

Anda juga bisa menggunakan:

Mapper.CreateMap<sourceModel, destinationModel>(MemberList.Destination);  

10
Jawaban ini seharusnya memiliki lebih banyak upvotes, bahkan mungkin ditandai sebagai jawabannya. Ini memecahkan masalah saya dan juga MemberList.Destinationakan memecahkan masalah ops.
Tedd Hansen

1
Ini tidak akan berfungsi jika Anda ingin mengabaikan beberapa properti pada sumber dan tujuan :)
RealWillyWoka

62
Bagi siapa pun yang datang kemudian, INI ADALAH JAWABAN YANG TEPAT UNTUK 5.0
Jimmy Bogard

3
terlihat bagus tetapi tidak bekerja untuk saya .. saya mencoba Sumber dan Tujuan, tetapi terus mengeluh tentang objek properti yang sama kehilangan peta
Sonic Soul

1
Menggunakan 6.0.2 dan ini bukan periode kerja. Setiap properti yang tidak dipetakan dari tujuan ke sumber, menimpa properti dalam sumber dengan nol dan 0. Ditambah kode tidak menjelaskan apa yang Anda lakukan, terutama jika Anda bekerja dalam tim. Itu sebabnya saya sangat tidak menyukai kode ini, dan mengapa saya lebih suka kata-kata pilihan seperti jawaban yang disarankan "IgnoreAllNonExisting"
sksallaj

222

Saya telah memperbarui ekstensi Can Gencer untuk tidak menimpa peta yang ada.

public static IMappingExpression<TSource, TDestination> 
    IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
    var sourceType = typeof (TSource);
    var destinationType = typeof (TDestination);
    var existingMaps = Mapper.GetAllTypeMaps().First(x => x.SourceType.Equals(sourceType) && x.DestinationType.Equals(destinationType));
    foreach (var property in existingMaps.GetUnmappedPropertyNames())
    {
        expression.ForMember(property, opt => opt.Ignore());
    }
    return expression;
}

Pemakaian:

Mapper.CreateMap<SourceType, DestinationType>()
                .ForMember(prop => x.Property, opt => opt.MapFrom(src => src.OtherProperty))
                .IgnoreAllNonExisting();

4
+1, Terima kasih telah mengirimkan solusi ini. Butuh beberapa jam untuk mencari tahu bug aneh ketika saya menggunakan solusi di goo.gl/rG7SL , sampai saya tersandung ke posting ini lagi.
Nordin

3
Saya merekomendasikan metode Yohanb di bawah ini untuk ini. Ada beberapa kasus sudut yang ini tidak berhasil karena muncul.
Jon Barker

3
Bisakah ini dilakukan di AutoMapper 4.2? (The Mapper.GetAllTypeMaps()sudah ditinggalkan)
mrmashal

14
Untuk versi AutoMapper 5+ ganti saja Mapper.GetAllTypeMaps()dengan Mapper.Configuration.GetAllTypeMaps(). Berikut ini adalah referensi github.com/AutoMapper/AutoMapper/issues/1252
Sergey G.

5
Untuk orang baru membaca ini. Jawaban ini untuk AutoMapper 2 dan pada saat menulis komentar ini kita berada di versi 6. Ini adalah hack dan cara yang jauh lebih bersih adalah dengan menggunakan enumer MemberList. Lihat masalah Github 1839 dan solusi yang lebih baik. github.com/AutoMapper/AutoMapper/issues/1839 Jadi contoh: stackoverflow.com/a/31182390/3850405
Ogglas

83

Saya sudah bisa melakukan ini dengan cara berikut:

Mapper.CreateMap<SourceType, DestinationType>().ForAllMembers(opt => opt.Ignore());
Mapper.CreateMap<SourceType, DestinationType>().ForMember(/*Do explicit mapping 1 here*/);
Mapper.CreateMap<SourceType, DestinationType>().ForMember(/*Do explicit mapping 2 here*/);
...

Catatan: Saya menggunakan AutoMapper v.2.0.


4
Terima kasih banyak! itu bekerja seperti pesona. saya mencoba dulu untuk membuat panggilan tetapi ForAllMembers baru saja mengembalikan batal :(. Tidak jelas bahwa IgnoreAll sebelumnya dapat dimodifikasi nanti.
SeriousM

5
Saya juga tidak suka cara ini .. jika Anda memiliki 50 anggota, dan Anda ingin mengabaikan 25 .. lalu apa gunanya automapper jika Anda masih harus mengabaikan 25 anggota. Jika nama cocok, dan ada properti yang tidak cocok .. mengapa tidak membuatnya jelas untuk memberitahu automapper agar tidak cocok dengan properti yang belum dipetakan dan dengan meneruskan semua pengetikan?
sksallaj

71

Versi 5.0.0-beta-1 dari AutoMapper memperkenalkan ForAllOtherMembersmetode ekstensi sehingga Anda sekarang dapat melakukan ini:

CreateMap<Source, Destination>()
    .ForMember(d => d.Text, o => o.MapFrom(s => s.Name))
    .ForMember(d => d.Value, o => o.MapFrom(s => s.Id))
    .ForAllOtherMembers(opts => opts.Ignore());

Ketahuilah bahwa ada keuntungan untuk memetakan secara eksplisit setiap properti karena Anda tidak akan pernah mendapatkan masalah pemetaan gagal secara diam-diam yang timbul ketika Anda lupa memetakan properti.

Mungkin dalam kasus Anda mungkin bijaksana untuk mengabaikan semua anggota lain dan menambahkan TODOuntuk kembali dan membuat ini eksplisit setelah frekuensi perubahan pada kelas ini diselesaikan.


3
Luar biasa ini sampai versi 5. Lihat berapa banyak suara-up dan mencoba jawaban untuk pertanyaan ini ... ada yang salah dengan pemerintahan Automapper saya bertanya-tanya?
Jack Ukleja

Terima kasih untuk ini, butuh beberapa saat untuk gulir ke bawah tapi ini, tetapi berfungsi dengan baik.
cobolstinks

2
Anda bahkan dapat menempatkan baris ForAllOtherMembers terlebih dahulu dan semuanya akan berfungsi sama, yang bagus jika Anda memiliki semacam konfigurasi kelas dasar.
N73k

Sekarang ini pendekatan yang disukai. Bertanya-tanya apakah OP dapat mengubah jawaban yang diterima?
Chase Florell

1
Apakah ada yang setara dengan mengabaikan properti di objek sumber? Sesuatu seperti ForAllOtherSourceMembers?
SuperJMN

44

Pada AutoMapper 5.0, .TypeMapproperti on IMappingExpressionsudah tidak ada, artinya solusi 4.2 tidak lagi berfungsi. Saya telah membuat solusi yang menggunakan fungsi asli tetapi dengan sintaks yang berbeda:

var config = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<Src, Dest>();
    cfg.IgnoreUnmapped();        // Ignores unmapped properties on all maps
    cfg.IgnoreUnmapped<Src, Dest>();  // Ignores unmapped properties on specific map
});

// or add  inside a profile
public class MyProfile : Profile
{
   this.IgnoreUnmapped();
   CreateMap<MyType1, MyType2>();
}

Penerapan:

public static class MapperExtensions
{
    private static void IgnoreUnmappedProperties(TypeMap map, IMappingExpression expr)
    {
        foreach (string propName in map.GetUnmappedPropertyNames())
        {
            if (map.SourceType.GetProperty(propName) != null)
            {
                expr.ForSourceMember(propName, opt => opt.Ignore());
            }
            if (map.DestinationType.GetProperty(propName) != null)
            {
                expr.ForMember(propName, opt => opt.Ignore());
            }
        }
    }

    public static void IgnoreUnmapped(this IProfileExpression profile)
    {
        profile.ForAllMaps(IgnoreUnmappedProperties);
    }

    public static void IgnoreUnmapped(this IProfileExpression profile, Func<TypeMap, bool> filter)
    {
        profile.ForAllMaps((map, expr) =>
        {
            if (filter(map))
            {
                IgnoreUnmappedProperties(map, expr);
            }
        });
    }

    public static void IgnoreUnmapped(this IProfileExpression profile, Type src, Type dest)
    {
        profile.IgnoreUnmapped((TypeMap map) => map.SourceType == src && map.DestinationType == dest);
    }

    public static void IgnoreUnmapped<TSrc, TDest>(this IProfileExpression profile)
    {
        profile.IgnoreUnmapped(typeof(TSrc), typeof(TDest));
    }
}

3
Bagaimana Anda menggunakan ini dalam CreateMap<TSource,TDest>()ekspresi berantai dalam Profile?
jmoerdyk

2
Terima kasih untuk ini. Metode GetUnmappedPropertyNames mengembalikan semua nama properti yang belum dipetakan, baik pada sumber dan tujuan, yang tampaknya rusak pada peta terbalik, jadi saya harus membuat perubahan kecil ke IgnoreUnmapped untuk memeriksa apakah properti yang belum dipetakan berada di sumber atau tujuan dan abaikan demikian. Berikut biola yang menunjukkan masalah dan pembaruan: dotnetfiddle.net/vkRGJv
Mun

1
Saya telah memperbarui jawaban saya untuk memasukkan temuan Anda - Saya tidak menggunakan pemetaan Sumber jadi belum menemukan ini! Terima kasih.
Richard

1
Ini tidak berfungsi pada PCL tanpa refleksi tersedia, GetProperty (propName) tidak ada.
George Taskos

Saya tidak melihat bagaimana ini merupakan solusi untuk pertanyaan itu, atau bagaimana ini bahkan melakukan apa pun. Properti yang belum dipetakan akan diabaikan - karena belum dipetakan . Poster itu mengatakan "bagaimana Anda mengabaikan alat peraga kecuali mereka dipetakan secara eksplisit ". Itu berarti bahwa jika saya memiliki Src.MyProp dan Dest.MyProp, pemetaan itu harus diabaikan kecuali ada panggilan eksplisit ke MapFrom & ForMember untuk MyProp. Jadi, pemetaan default perlu diabaikan. Satu-satunya hal yang dilakukan solusi ini adalah untuk membuat hal config-valid-assert lulus - yang bagaimanapun tidak Anda perlukan agar pemetaan berfungsi.
N73k

17

Sudah ada beberapa tahun sejak pertanyaan diajukan, tetapi metode ekstensi ini tampak lebih bersih bagi saya, menggunakan versi AutoMapper saat ini (3.2.1):

public static IMappingExpression<TSource, TDestination> IgnoreUnmappedProperties<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
    var typeMap = Mapper.FindTypeMapFor<TSource, TDestination>();
    if (typeMap != null)
    {
        foreach (var unmappedPropertyName in typeMap.GetUnmappedPropertyNames())
        {
            expression.ForMember(unmappedPropertyName, opt => opt.Ignore());
        }
    }

    return expression;
}

16

Bagi mereka yang menggunakan API non-statis di versi 4.2.0 dan di atas, metode ekstensi berikut (ditemukan di sini di AutoMapperExtensionskelas) dapat digunakan:

// from http://stackoverflow.com/questions/954480/automapper-ignore-the-rest/6474397#6474397
public static IMappingExpression IgnoreAllNonExisting(this IMappingExpression expression)
{
    foreach(var property in expression.TypeMap.GetUnmappedPropertyNames())
    {
        expression.ForMember(property, opt => opt.Ignore());
    }
    return expression;
}

Yang penting di sini adalah bahwa begitu API statis dihapus, kode seperti Mapper.FindTypeMapForitu tidak akan berfungsi lagi, maka penggunaan expression.TypeMapbidang tersebut.


7
Pada 5.0, expression.TypeMaptidak lagi tersedia. Inilah solusi saya untuk 5.0
Richard

Saya harus menggunakan public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)untuk memperbaiki masalah tipe.
Nick M

16

Untuk Automapper 5.0 untuk melewati semua properti yang belum dipetakan, Anda hanya perlu memasukkannya

.ForAllOtherMembers (x => x.Ignore ());

di akhir profil Anda.

Sebagai contoh:

internal class AccountInfoEntityToAccountDtoProfile : Profile
{
    public AccountInfoEntityToAccountDtoProfile()
    {
        CreateMap<AccountInfoEntity, AccountDto>()
           .ForMember(d => d.Id, e => e.MapFrom(s => s.BankAcctInfo.BankAcctFrom.AcctId))
           .ForAllOtherMembers(x=>x.Ignore());
    }
}

Dalam hal ini hanya bidang Id untuk objek output yang akan diselesaikan, semua yang lain akan dilewati. Bekerja seperti pesona, sepertinya kita tidak membutuhkan ekstensi rumit lagi!


10

Saya telah memperbarui jawaban Robert Schroeder untuk AutoMapper 4.2. Dengan konfigurasi mapper non-statis, kita tidak dapat menggunakan Mapper.GetAllTypeMaps(), tetapi expressionmemiliki referensi ke yang diperlukan TypeMap:

public static IMappingExpression<TSource, TDestination> 
    IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
    foreach (var property in expression.TypeMap.GetUnmappedPropertyNames())
    {
        expression.ForMember(property, opt => opt.Ignore());
    }
    return expression;
}

Tidak berfungsi di AutoMapper 5.0. Properti .TypeMap di IMappingExpression tidak tersedia. Untuk versi 5. + lihat ekstensi dalam jawaban Richard
Michael Freidgeim

Bekerja dengan AM 4.2
Leszek P

8

Bagaimana Anda lebih suka menentukan bahwa anggota tertentu diabaikan? Apakah ada konvensi, atau kelas dasar, atau atribut yang ingin Anda terapkan? Setelah Anda masuk ke bisnis menentukan semua pemetaan secara eksplisit, saya tidak yakin nilai apa yang akan Anda dapatkan dari AutoMapper.


Jimmy, kamu ada benarnya tentang explicitness. Adapun cara bagaimana mencapai ini dengan cara yang paling elegan: kelas dasar dan atribut tidak akan berfungsi dalam situasi ini, karena kelas target tidak benar-benar di bawah kendali saya - mereka di-autogenerasi dari kontrak data XSD, jadi orang harus memiliki untuk mengedit kode ini secara manual setelah setiap siklus generasi. Saya kira solusinya tergantung pada kasus nyata. Mungkin antarmuka yang lancar mirip dengan yang disediakan Windsor Castle untuk memilih komponen mana yang akan didaftarkan dalam wadah yang bisa menjadi solusi?
Igor Brejc

Ah itu lebih masuk akal sekarang. Itu fitur yang menarik, saya akan melihatnya pada jangka waktu 2.1.
Jimmy Bogard

2
Bagaimana kalau hanya memiliki nilai yang dapat dikonfigurasi di mana Anda dapat "mengabaikan" semua bidang yang tidak ada.
Ricardo Sanchez

6
Ini bukan jawaban untuk pertanyaan itu.
user2864740

Hai Jimmy, Anda penulisnya, benar? Saya ingin dapat mengabaikan semua properti yang tidak ada sebagai perilaku default (dapat dikontrol oleh flag). Juga, saya mengalami kesalahan aneh dari AutoMapper. Saya tidak dapat mengetahuinya. Itu tidak memberi saya spesifik.
Naomi

7

Ini sepertinya pertanyaan lama tetapi saya pikir saya akan memposting jawaban saya untuk orang lain yang terlihat seperti saya.

Saya menggunakan ConstructUsing, penginisialisasi objek ditambah dengan ForAllMembers abaikan misalnya

    Mapper.CreateMap<Source, Target>()
        .ConstructUsing(
            f =>
                new Target
                    {
                        PropVal1 = f.PropVal1,
                        PropObj2 = Map<PropObj2Class>(f.PropObj2),
                        PropVal4 = f.PropVal4
                    })
        .ForAllMembers(a => a.Ignore());

1

Satu-satunya informasi tentang mengabaikan banyak anggota adalah utas ini - http://groups.google.com/group/automapper-users/browse_thread/thread/9928ce9f2ffa641f . Saya pikir Anda dapat menggunakan trik yang digunakan dalam ProvidingCommonBaseClassConfiguration untuk mengabaikan properti umum untuk kelas yang sama.
Dan tidak ada informasi tentang fungsi "Abaikan sisanya". Saya telah melihat kode sebelumnya dan menurut saya akan sangat dan sangat sulit untuk menambahkan fungsionalitas tersebut. Anda juga dapat mencoba menggunakan beberapa atribut dan menandainya dengan properti yang diabaikan dan menambahkan beberapa kode umum / umum untuk mengabaikan semua properti yang ditandai.


1
Mungkin salah satu caranya adalah dengan menggunakan metode ForAllMembers dan mengimplementasikan IMemberConfigurationExpression saya sendiri yang menerima string yang berisi nama properti dari properti yang tidak boleh diabaikan, dan kemudian pergi melalui sisanya dan memanggil Abaikan (). Hanya sebuah ide, saya tidak yakin apakah itu akan berhasil.
Igor Brejc

Ya, ini bisa bekerja juga, tetapi metode ini lebih rumit daripada menggunakan atribut tetapi menawarkan lebih banyak fleksibilitas. Sangat disayangkan bahwa tidak ada peluru perak :(.
zihotki

1

Saya tahu ini adalah pertanyaan lama, tetapi @jmoerdyk dalam pertanyaan Anda:

Bagaimana Anda menggunakan ini dalam ekspresi CreateMap () berantai dalam Profil?

Anda dapat menggunakan jawaban ini seperti ini di dalam profil Ctor

this.IgnoreUnmapped();
CreateMap<TSource, Tdestination>(MemberList.Destination)
.ForMember(dest => dest.SomeProp, opt => opt.MapFrom(src => src.OtherProp));

0

Anda dapat menggunakan ForAllMembers, daripada hanya menimpa yang diperlukan seperti ini

public static IMappingExpression<TSource, TDest> IgnoreAll<TSource, TDest>(this IMappingExpression<TSource, TDest> expression)
        {
            expression.ForAllMembers(opt => opt.Ignore());
            return expression;
        }

Hati-hati, itu akan mengabaikan semua, dan jika Anda tidak akan menambahkan pemetaan khusus, mereka sudah diabaikan dan tidak akan berfungsi

juga, saya ingin mengatakan, jika Anda memiliki unit test untuk AutoMapper. Dan Anda menguji bahwa semua model dengan semua properti dipetakan dengan benar, Anda seharusnya tidak menggunakan metode ekstensi tersebut

Anda harus menulis abaikan secara eksplisit


-1

Solusi saat ini (versi 9) untuk mengabaikan properti yang tidak ada di tipe tujuan adalah membuat pemetaan terbalik dan membalikkannya:

var config = new MapperConfiguration(cfg => {
  cfg.CreateMap<TheActualDestinationType, TheActualSourceType>().ReverseMap();
});

-2

Dalam versi 3.3.1 Anda cukup menggunakan IgnoreAllPropertiesWithAnInaccessibleSetter()atau IgnoreAllSourcePropertiesWithAnInaccessibleSetter()metode.


6
Ini tidak berfungsi sesuai pertanyaan pengirim asli. Metode ini hanya mengabaikan properti yang dilindungi atau pribadi, bukan properti yang hilang dari sumber tetapi hadir dalam jenis tujuan.
Dan
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.